<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 6.3.0">
  <link rel="apple-touch-icon" sizes="180x180" href="/xlrblog/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/xlrblog/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/xlrblog/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/xlrblog/images/logo.svg" color="#222">

<link rel="stylesheet" href="/xlrblog/css/main.css">


<link rel="stylesheet" href="/xlrblog/lib/font-awesome/css/all.min.css">

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"gitee.com","root":"/xlrblog/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":true,"show_result":true,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":false},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},"path":"search.json"};
  </script>

  <meta name="description" content="Linux基础入门 基本概念及操作Linux终端通常我们在使用 Linux 时，并不是直接与系统打交道，而是通过一个叫做 Shell 的中间程序来完成的，在图形界面下为了实现让我们在一个窗口中完成用户输入和显示输出，Linux 系统还提供了一个叫做终端模拟器的程序（Terminal）。 下面是几个比较常见的终端模拟器： gnome-terminal，Konsole，xterm，rxvt，kvt，n">
<meta property="og:type" content="article">
<meta property="og:title" content="Linux基础入门">
<meta property="og:url" content="https://gitee.com/xlr0306/2023/08/05/Linux%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/index.html">
<meta property="og:site_name" content="君不见的博客">
<meta property="og:description" content="Linux基础入门 基本概念及操作Linux终端通常我们在使用 Linux 时，并不是直接与系统打交道，而是通过一个叫做 Shell 的中间程序来完成的，在图形界面下为了实现让我们在一个窗口中完成用户输入和显示输出，Linux 系统还提供了一个叫做终端模拟器的程序（Terminal）。 下面是几个比较常见的终端模拟器： gnome-terminal，Konsole，xterm，rxvt，kvt，n">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471792103.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471836262.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531472459081.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531472445671.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471910323.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471952505.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471982853.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731170296.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583140204433">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583140710447">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid1491336-20220512-1652348264006">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731216215.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583141675216">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583142076115">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583142261959">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid13labid3timestamp1454035714557.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid13labid3timestamp1454035855554.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731335264.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid13labid3timestamp1454035698068.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583145040679">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200616-1592274816723">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583145514469">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583145591124">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731417990.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583146790310">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583147815919">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/3-9.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/3-10.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148438097">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148552984">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148845314">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148964757">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/3-14.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583149616295">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583149700161">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200302-1583150177369">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/4-1.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid18510labid59timestamp1482919171956.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583207588297">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583207655389">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733883613.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733900438.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733939312.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583209669773">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583210207550">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733966731.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733991692.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734147663.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583213792916">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583213884277">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734168883.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734186668.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734202525.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734226305.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734243413.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583215158345">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583215559370">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339240610.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/5-2.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/5-3.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339264870.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339293501.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583220161661">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339433567.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583223324878">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583224278229">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583224422523">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583225164807">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339453618.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583225846911">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20210113-1610502774649">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226161762">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226577160">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226847941">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/5-8.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226953512">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200303-1583227074890">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid600404-20190428-1556438181236">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid61timestamp1532339561961.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523871472488.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/7-2.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523871955863.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523872284604.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339776332.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339755321.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339693208.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523873459128.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523874300781.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523925358180.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/7-12.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/7-13.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/7-14.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/7-15.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/7-16.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339794389.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6123timestamp1523930371175.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6123timestamp1523930924973.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6123timestamp1523931303648.png">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081467871829217">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468210358613">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468201394787">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523941816405.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523941985569.png">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468202029108">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468203483143">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468204230683">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523942683532.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523943532369.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523943327065.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523943647348.png">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468206283987">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468206856712">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/1/1700764/dc52d96ef7ca2bcde69ceab88f15537d-0">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/1/1700764/8f72e47862086647925ea14ef01442ae-0">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid1labid63timestamp1544148440172.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414664955.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/8-3.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414685006.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414709836.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414725827.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414808838.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6125timestamp1523946094712.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414849333.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414877239.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414886554.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414902443.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414948354.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414967936.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid346timestamp1532415296335.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6127timestamp1523951670892.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6127timestamp1523951876075.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid346timestamp1532415315324.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6127timestamp1523952144929.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid346timestamp1532415336263.png">
<meta property="og:image" content="https://doc.shiyanlou.com/linux_base/RegularExpression.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415381859.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6128timestamp1523954676432.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415422642.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415449222.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415467268.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415579510.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415685031.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid600404-20191015-1571118544931">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532416617431.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415757042.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415834591.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415838840.png">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/5673/1700764/f8f335bf157a7e63b5fbf62ed760ef89-0">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/1/1700764/a1d5a1fdb56a9c3554e92d13bebc03a8-0">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532415931977.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid600404labid6129timestamp1523958065018.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416001019.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416027450.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416061661.png">
<meta property="og:image" content="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416074969.png">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469062947147">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469027998669">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081468836854017">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469030455439">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469004994601">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469036077882">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469036715105">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469037134869">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469037555070">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469037666320">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469037983282">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469038840624">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469070319324">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469086224826">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469086474033">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469088103140">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469089342412">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469089837027">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469090040956">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469004994601">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469090893467">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469091089249">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469092567061">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469092779938">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469406921904">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469409885670">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/1379/871732/7bc699b28ff48cefee31fa859af518d9-0">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/uid871732-20200807-1596779861997">
<meta property="og:image" content="https://doc.shiyanlou.com/courses/1379/871732/dc97b5ebc3c1054d4e5a6070fa36773b-0">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469412303087">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469412472830">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469414492628">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469414801715">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469433052645">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469416361678">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469415269198">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469433052645">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469474419356">
<meta property="og:image" content="https://dn-simplecloud.shiyanlou.com/1135081469476364695">
<meta property="article:published_time" content="2023-08-05T07:48:09.000Z">
<meta property="article:modified_time" content="2023-08-05T07:53:25.701Z">
<meta property="article:author" content="君不见">
<meta property="article:tag" content="Linux">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471792103.png">

<link rel="canonical" href="https://gitee.com/xlr0306/2023/08/05/Linux%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-CN'
  };
</script>

  <title>Linux基础入门 | 君不见的博客</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/xlrblog/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">君不见的博客</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">记录生活中的点点滴滴</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/xlrblog/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a>

  </li>
        <li class="menu-item menu-item-tags">

    <a href="/xlrblog/tags/" rel="section"><i class="fa fa-tags fa-fw"></i>标签</a>

  </li>
        <li class="menu-item menu-item-categories">

    <a href="/xlrblog/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/xlrblog/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档</a>

  </li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup">
        <div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div id="search-result">
  <div id="no-result">
    <i class="fa fa-spinner fa-pulse fa-5x fa-fw"></i>
  </div>
</div>

    </div>
  </div>

</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://gitee.com/xlr0306/2023/08/05/Linux%E5%9F%BA%E7%A1%80%E5%85%A5%E9%97%A8/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/xlrblog/images/avatar.gif">
      <meta itemprop="name" content="君不见">
      <meta itemprop="description" content="君不见，黄河之水天上来，奔流到海不复回。">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="君不见的博客">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Linux基础入门
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">发表于</span>
              

              <time title="创建时间：2023-08-05 15:48:09 / 修改时间：15:53:25" itemprop="dateCreated datePublished" datetime="2023-08-05T15:48:09+08:00">2023-08-05</time>
            </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">分类于</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/xlrblog/categories/Linux/" itemprop="url" rel="index"><span itemprop="name">Linux</span></a>
                </span>
            </span>

          

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <p>Linux基础入门</p>
<h1 id="基本概念及操作"><a href="#基本概念及操作" class="headerlink" title="基本概念及操作"></a>基本概念及操作</h1><h2 id="Linux终端"><a href="#Linux终端" class="headerlink" title="Linux终端"></a>Linux终端</h2><p>通常我们在使用 Linux 时，并不是直接与系统打交道，而是通过一个叫做 Shell 的中间程序来完成的，在图形界面下为了实现让我们在一个窗口中完成用户输入和显示输出，Linux 系统还提供了一个叫做终端模拟器的程序（Terminal）。 下面是几个比较常见的终端模拟器： gnome-terminal，Konsole，xterm，rxvt，kvt，nxterm 和 eterm 。目前我们的实验中的终端程序是 xfce 桌面环境自带的 xfce-terminal 。不过要注意的是这里所说的终端（Terminal）和控制台（Console）是有区别的。</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471792103.png" alt="1"></p>
<p>终端本质上是对应着 Linux 上的 &#x2F;dev&#x2F;tty 设备，Linux 的多用户登录就是通过不同的 &#x2F;dev&#x2F;tty 设备完成的，Linux 默认提供了 6 个纯命令行界面的 “terminal”（准确的说这里应该是 6 个 virtual consoles）来让用户登录。在物理机系统上你可以通过使用<code>[Ctrl]</code>+<code>[Alt]</code>+<code>[F1]～[F6]</code>进行切换，不过在我们的在线实验环境中可能无法切换，因为特殊功能按键会被你的主机系统劫持。当你切换到其中一个终端后想要切换回图形界面，你可以按下<code>[Ctrl]</code>+<code>[Alt]</code>+<code>[F7]</code>来完成。</p>
<h3 id="Shell"><a href="#Shell" class="headerlink" title="Shell"></a>Shell</h3><p>通常在图形界面中对实际体验带来差异的不是上述的不同发行版的各种终端模拟器，而是这个 Shell（壳）。有壳就有核，这里的核就是指 UNIX&#x2F;Linux 内核，Shell 是指“提供给使用者使用界面”的软件（命令解析器），类似于 DOS 下的 command（命令行）和后来的 cmd.exe 。普通意义上的 Shell 就是可以接受用户输入命令的程序。它之所以被称作 Shell 是因为它隐藏了操作系统底层的细节。同样的 UNIX&#x2F;Linux 下的图形用户界面 GNOME 和 KDE，有时也被叫做“虚拟 shell”或“图形 shell”。</p>
<p>UNIX&#x2F;Linux 操作系统下的 Shell 既是用户交互的界面，也是控制系统的脚本语言。当然这一点也有别于 Windows 下的命令行，虽然该命令行也提供了很简单的控制语句。在 Windows 操作系统下，有些用户从来都不会直接使用 Shell，然而在 UNIX 系列操作系统下，Shell 仍然是控制系统启动、X11 启动和很多其它实用工具的脚本解释程序。</p>
<p>在 UNIX&#x2F;Linux 中比较流行的常见的 Shell 有 bash、zsh、ksh、csh 等等，Ubuntu 终端默认使用的是 bash，默认的桌面环境是 GNOME 或者 Unity（基于 GNOME），但我们的环境中使用的分别是 zsh 和 xfce。</p>
<h3 id="命令行操作体验"><a href="#命令行操作体验" class="headerlink" title="命令行操作体验"></a>命令行操作体验</h3><p>在 linux 中，最最重要的就是命令，这就包含了 2 个过程，输入和输出</p>
<ul>
<li>输入：输入当然就是打开终端，然后按键盘输入，然后按回车，输入格式一般就是这类的</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#创建一个名为 file 的文件，touch是一个命令</span><br><span class="line">touch file</span><br><span class="line"></span><br><span class="line">#进入一个目录，cd是一个命令</span><br><span class="line">cd /etc/</span><br><span class="line"></span><br><span class="line">#查看当前所在目录</span><br><span class="line">pwd</span><br></pre></td></tr></table></figure>

<ul>
<li>输出：输出会返回你想要的结果，比如你要看什么文件，就会返回文件的内容。如果只是执行，执行失败会告诉你哪里错了，如果执行成功那么会没有输出，因为 linux 的哲学就是：没有结果就是最好的结果</li>
</ul>
<h4 id="开始"><a href="#开始" class="headerlink" title="开始"></a>开始</h4><p>如图，双击桌面上的 <code>Xfce 终端</code> 图标打开终端后系统会自动运行 Shell 程序，然后我们就可以输入命令让系统来执行了：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471836262.png" alt="1"></p>
<h4 id="1-重要快捷键"><a href="#1-重要快捷键" class="headerlink" title="1) 重要快捷键"></a>1) 重要快捷键</h4><p>真正学习命令行之前，你先要掌握几个十分有用、必需掌握的小技巧：</p>
<h5 id="Tab"><a href="#Tab" class="headerlink" title="[Tab]"></a>[Tab]</h5><p>使用<code>Tab</code>键来进行命令补全，<code>Tab</code>键一般是在字母<code>Q</code>旁边，这个技巧给你带来的最大的好处就是当你忘记某个命令的全称时可以只输入它的开头的一部分，然后按下<code>Tab</code>键就可以得到提示或者帮助完成：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531472459081.png" alt="1"></p>
<p>当然不止补全命令，补全目录、补全命令参数都是没问题的：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531472445671.png" alt="1"></p>
<h5 id="Ctrl-c"><a href="#Ctrl-c" class="headerlink" title="[Ctrl+c]"></a>[Ctrl+c]</h5><p>想想你有没有遇到过这种情况，当你在 Linux 命令行中无意输入了一个不知道的命令，或者错误地使用了一个命令，导致在终端里出现了你无法预料的情况，比如，屏幕上只有光标在闪烁却无法继续输入命令，或者不停地输出一大堆你不想要的结果。你想要立即停止并恢复到你可控的状态，那该怎么办呢？这时候你就可以使用<code>Ctrl+c</code>键来强行终止当前程序（你可以放心它并不会使终端退出）。</p>
<p>尝试输入以下命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tail</span><br></pre></td></tr></table></figure>

<p>然后你会发现你接下来的输入都没有任何反应了，只是将你输入的东西显示出来，现在你可以使用<code>Ctrl+c</code>，来中断这个你目前可能还不知道是什么的程序（在后续课程中我们会具体解释这个<code>tail</code>命令是什么）。</p>
<p>又或者输入：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find /</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471910323.png" alt="pic"></p>
<p>显然这不是你想的结果，可以使用<code>Ctrl+c</code>结束。</p>
<p>虽然这个按着很方便，但不要随便按，因为有时候，当你看到终端没有任何反应或提示，也不能接受你的输入时，可能只是运行的程序需要你耐心等一下，就不要急着按<code>Ctrl+c</code>了。</p>
<h5 id="其他一些常用快捷键"><a href="#其他一些常用快捷键" class="headerlink" title="其他一些常用快捷键"></a>其他一些常用快捷键</h5><table>
<thead>
<tr>
<th>按键</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td><code>Ctrl+d</code></td>
<td>键盘输入结束或退出终端</td>
</tr>
<tr>
<td><code>Ctrl+s</code></td>
<td>暂停当前程序，暂停后按下任意键恢复运行</td>
</tr>
<tr>
<td><code>Ctrl+z</code></td>
<td>将当前程序放到后台运行，恢复到前台为命令<code>fg</code></td>
</tr>
<tr>
<td><code>Ctrl+a</code></td>
<td>将光标移至输入行头，相当于<code>Home</code>键</td>
</tr>
<tr>
<td><code>Ctrl+e</code></td>
<td>将光标移至输入行末，相当于<code>End</code>键</td>
</tr>
<tr>
<td><code>Ctrl+k</code></td>
<td>删除从光标所在位置到行末</td>
</tr>
<tr>
<td><code>Alt+Backspace</code></td>
<td>向前删除一个单词</td>
</tr>
<tr>
<td><code>Shift+PgUp</code></td>
<td>将终端显示向上滚动</td>
</tr>
<tr>
<td><code>Shift+PgDn</code></td>
<td>将终端显示向下滚动</td>
</tr>
</tbody></table>
<h4 id="2-学会利用历史输入命令"><a href="#2-学会利用历史输入命令" class="headerlink" title="2) 学会利用历史输入命令"></a>2) 学会利用历史输入命令</h4><p>很简单，你可以使用键盘上的方向上键<code>↑</code>，恢复你之前输入过的命令，你一试便知。</p>
<h4 id="3-学会使用通配符"><a href="#3-学会使用通配符" class="headerlink" title="3) 学会使用通配符"></a>3) 学会使用通配符</h4><p>通配符是一种特殊语句，主要有星号（*）和问号（?），用来对字符串进行模糊匹配（比如文件名、参数名）。当查找文件夹时，可以使用它来代替一个或多个真正字符；当不知道真正字符或者懒得输入完整名字时，常常使用通配符代替一个或多个真正字符。</p>
<p>终端里面输入的通配符是由 Shell 处理的，不是由所涉及的命令语句处理的，它只会出现在命令的“参数值”里（它不能出现在命令名称里， 命令不记得，那就用<code>Tab</code>补全）。当 Shell 在“参数值”中遇到了通配符时，Shell 会将其当作路径或文件名在磁盘上搜寻可能的匹配：若符合要求的匹配存在，则进行代换（路径扩展）；否则就将该通配符作为一个普通字符传递给“命令”，然后再由命令进行处理。总之，通配符实际上就是一种 Shell 实现的路径扩展功能。在通配符被处理后， Shell 会先完成该命令的重组，然后继续处理重组后的命令，直至执行该命令。</p>
<p>首先回到用户家目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br></pre></td></tr></table></figure>

<p>然后使用 touch 命令创建 2 个文件，后缀都为 txt：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch asd.txt fgh.txt</span><br></pre></td></tr></table></figure>

<p>可以给文件随意命名，假如过了很长时间，你已经忘了这两个文件的文件名，现在你想在一大堆文件中找到这两个文件，就可以使用通配符：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls *.txt</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471952505.png" alt="1"></p>
<p>在创建文件的时候，如果需要一次性创建多个文件，比如：<strong>“love_1_linux.txt，love_2_linux.txt，… love_10_linux.txt”</strong>。在 Linux 中十分方便：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">touch love_&#123;1..10&#125;_shiyanlou.txt</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid2timestamp1531471982853.png" alt="pic"></p>
<p>Shell 常用通配符：</p>
<table>
<thead>
<tr>
<th>字符</th>
<th>含义</th>
</tr>
</thead>
<tbody><tr>
<td><code>*</code></td>
<td>匹配 0 或多个字符</td>
</tr>
<tr>
<td><code>?</code></td>
<td>匹配任意一个字符</td>
</tr>
<tr>
<td><code>[list]</code></td>
<td>匹配 list 中的任意单一字符</td>
</tr>
<tr>
<td><code>[^list]</code></td>
<td>匹配 除 list 中的任意单一字符以外的字符</td>
</tr>
<tr>
<td><code>[c1-c2]</code></td>
<td>匹配 c1-c2 中的任意单一字符 如：[0-9][a-z]</td>
</tr>
<tr>
<td><code>&#123;string1,string2,...&#125;</code></td>
<td>匹配 string1 或 string2 (或更多)其一字符串</td>
</tr>
<tr>
<td><code>&#123;c1..c2&#125;</code></td>
<td>匹配 c1-c2 中全部字符 如{1..10}</td>
</tr>
</tbody></table>
<h4 id="4-学会在命令行中获取帮助"><a href="#4-学会在命令行中获取帮助" class="headerlink" title="4) 学会在命令行中获取帮助"></a>4) 学会在命令行中获取帮助</h4><p>在 Linux 环境中，如果你遇到困难，可以使用<code>man</code>命令，它是<code>Manual pages</code>的缩写。</p>
<p>Manual pages 是 UNIX 或类 UNIX 操作系统中在线软件文档的一种普遍的形式， 内容包括计算机程序（包括库和系统调用）、正式的标准和惯例，甚至是抽象的概念。用户可以通过执行<code>man</code>命令调用手册页。</p>
<p>你可以使用如下方式来获得某个命令的说明和使用方式的详细介绍：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">man &lt;command_name&gt;</span><br></pre></td></tr></table></figure>

<p>比如你想查看 man 命令本身的使用方式，你可以输入：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">man man</span><br></pre></td></tr></table></figure>

<p>通常情况下，man 手册里面的内容都是英文的，这就要求你有一定的英文基础。man 手册的内容很多，涉及了 Linux 使用过程中的方方面面。为了便于查找，man 手册被进行了分册（分区段）处理，在 Research UNIX、BSD、OS X 和 Linux 中，手册通常被分为 8 个区段，安排如下：</p>
<table>
<thead>
<tr>
<th>区段</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>1</td>
<td>一般命令</td>
</tr>
<tr>
<td>2</td>
<td>系统调用</td>
</tr>
<tr>
<td>3</td>
<td>库函数，涵盖了 C 标准函数库</td>
</tr>
<tr>
<td>4</td>
<td>特殊文件（通常是&#x2F;dev 中的设备）和驱动程序</td>
</tr>
<tr>
<td>5</td>
<td>文件格式和约定</td>
</tr>
<tr>
<td>6</td>
<td>游戏和屏保</td>
</tr>
<tr>
<td>7</td>
<td>杂项</td>
</tr>
<tr>
<td>8</td>
<td>系统管理命令和守护进程</td>
</tr>
</tbody></table>
<p>要查看相应区段的内容，就在 man 后面加上相应区段的数字即可，如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">man 1 ls</span><br></pre></td></tr></table></figure>

<p>会显示第一区段中的<code>ls</code>命令 man 页面。</p>
<p>所有的手册页遵循一个常见的布局，为了通过简单的 ASCII 文本展示而被优化，而这种情况下可能没有任何形式的高亮或字体控制。一般包括以下部分内容：</p>
<p><strong>NAME（名称）</strong></p>
<blockquote>
<p>该命令或函数的名称，接着是一行简介。</p>
</blockquote>
<p><strong>SYNOPSIS（概要）</strong></p>
<blockquote>
<p>对于命令，正式的描述它如何运行，以及需要什么样的命令行参数。对于函数，介绍函数所需的参数，以及哪个头文件包含该函数的定义。</p>
</blockquote>
<p><strong>DESCRIPTION（说明）</strong></p>
<blockquote>
<p>命令或函数功能的文本描述。</p>
</blockquote>
<p><strong>EXAMPLES（示例）</strong></p>
<blockquote>
<p>常用的一些示例。</p>
</blockquote>
<p><strong>SEE ALSO（参见）</strong></p>
<blockquote>
<p>相关命令或函数的列表。</p>
</blockquote>
<p>也可能存在其它部分内容，但这些部分没有得到跨手册页的标准化。常见的例子包括：OPTIONS（选项），EXIT STATUS（退出状态），ENVIRONMENT（环境），BUGS（程序漏洞），FILES（文件），AUTHOR（作者），REPORTING BUGS（已知漏洞），HISTORY（历史）和 COPYRIGHT（版权）。</p>
<p>通常 man 手册中的内容很多，你可能不太容易找到你想要的结果，不过幸运的是你可以在 man 中使用搜索<code>/&lt;你要搜索的关键字&gt;</code>，查找完毕后你可以使用<code>n</code>键切换到下一个关键字所在处，<code>shift+n</code>为上一个关键字所在处。使用<code>Space</code>（空格键）翻页，<code>Enter</code>（回车键）向下滚动一行，或者使用<code>k</code>，<code>j</code>（vim 编辑器的移动键）进行向前向后滚动一行。按下<code>h</code>键为显示使用帮助（因为 man 使用 less 作为阅读器，实为<code>less</code>工具的帮助），按下<code>q</code>退出。</p>
<p>想要获得更详细的帮助，你还可以使用<code>info</code>命令，不过通常使用<code>man</code>就足够了。如果你知道某个命令的作用，只是想快速查看一些它的某个具体参数的作用，那么你可以使用<code>--help</code>参数，大部分命令都会带有这个参数，如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls --help</span><br></pre></td></tr></table></figure>

<h1 id="用户及文件权限管理"><a href="#用户及文件权限管理" class="headerlink" title="用户及文件权限管理"></a>用户及文件权限管理</h1><h2 id="Linux用户管理"><a href="#Linux用户管理" class="headerlink" title="Linux用户管理"></a>Linux用户管理</h2><h3 id="查看用户"><a href="#查看用户" class="headerlink" title="查看用户"></a>查看用户</h3><p>请打开终端，输入命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">who am i</span><br><span class="line"></span><br><span class="line"># 或者</span><br><span class="line"></span><br><span class="line">who mom likes</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731170296.png" alt="3-2.1-1"></p>
<p>输出的第一列表示打开当前伪终端的用户的用户名（要查看当前登录用户的用户名，去掉空格直接使用 <code>whoami</code> 即可），第二列的 <code>pts/0</code> 中 <code>pts</code> 表示伪终端，所谓伪是相对于 <code>/dev/tty</code> 设备而言的，还记得上一节讲终端时的那七个使用 <code>[Ctrl]</code>+<code>[Alt]</code>+<code>[F1]～[F7]</code> 进行切换的 <code>/dev/tty</code> 设备么，这是“真终端”，伪终端就是当你在图形用户界面使用 <code>/dev/tty7</code> 时每打开一个终端就会产生一个伪终端，<code>pts/0</code> 后面那个数字就表示打开的伪终端序号，你可以尝试再打开一个终端，然后在里面输入 <code>who am i</code>，看第二列是不是就变成 <code>pts/1</code> 了，第三列则表示当前伪终端的启动时间。</p>
<p>还有一点需要注意的是，在某些环境中 <code>who am i</code> 和 <code>who mom likes</code> 命令不会输出任何内容，这是因为当前使用的 Shell 不是登录式 Shell（login shell），没有用户与 <code>who</code> 的 stdin 相关联，因此不会输出任何内容。登录 Shell 是指用户使用自己的 user ID 登录交互式 shell 的第一个进程，判断是不是登录 Shell 可以执行 <code>echo $0</code> 命令，如果返回 zsh、&#x2F;bin&#x2F;zsh、&#x2F;bin&#x2F;bash 这种格式，说明是非登录式 Shell（non-login shell）；如果返回 -zsh、-bash 则说明是登录式 Shell，这时你执行 <code>who am i</code> 就会有输出。</p>
<p>例如我在本地的 Ubuntu 系统上输入这个命令就不会有提示。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583140204433" alt="图片描述"></p>
<p>此时我们只需要打开一个新的 Shell 终端例如 Tmux，或者通过 ssh 登录到本机，再在新的终端里执行命令即可。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tmux</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583140710447" alt="图片描述"></p>
<p>我们环境里打开的终端是 xfce4-terminal 模拟终端，默认不是直接打开的 login hell，所以也没有输出。</p>
<p>除了上面介绍的手动启动 Shell 外，我们还可以选择手动配置成 login shell，点击终端上方菜单的「Edit」按钮，再选择「Preferences」，勾选 Command 下方的两个选项，然后关闭终端，重新打开终端，执行 <code>who am i</code> 命令就可以看到输出了。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid1491336-20220512-1652348264006" alt="图片描述"></p>
<p><code>who</code> 命令其它常用参数</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-a</code></td>
<td>打印能打印的全部</td>
</tr>
<tr>
<td><code>-d</code></td>
<td>打印死掉的进程</td>
</tr>
<tr>
<td><code>-m</code></td>
<td>同<code>am i</code>，<code>mom likes</code></td>
</tr>
<tr>
<td><code>-q</code></td>
<td>打印当前登录用户数及用户名</td>
</tr>
<tr>
<td><code>-u</code></td>
<td>打印当前登录用户登录信息</td>
</tr>
<tr>
<td><code>-r</code></td>
<td>打印运行等级</td>
</tr>
</tbody></table>
<h3 id="创建用户"><a href="#创建用户" class="headerlink" title="创建用户"></a>创建用户</h3><p>在 Linux 系统里， <code>root</code> 账户拥有整个系统至高无上的权限，比如新建和添加用户。</p>
<blockquote>
<p>root 权限，系统权限的一种，与 SYSTEM 权限可以理解成一个概念，但高于 Administrator 权限，root 是 Linux 和 UNIX 系统中的超级管理员用户帐户，该帐户拥有整个系统至高无上的权力，所有对象他都可以操作，所以很多黑客在入侵系统的时候，都要把权限提升到 root 权限，这个操作等同于在 Windows 下就是将新建的非法帐户添加到 Administrators 用户组。更比如安卓操作系统中（基于 Linux 内核）获得 root 权限之后就意味着已经获得了手机的最高权限，这时候你可以对手机中的任何文件（包括系统文件）执行所有增、删、改、查的操作。</p>
</blockquote>
<p>大部分 Linux 系统在安装时都会建议用户新建一个用户而不是直接使用 root 用户进行登录，当然也有直接使用 root 登录的例如 Kali（基于 Debian 的 Linux 发行版，集成大量工具软件，主要用于数字取证的操作系统）。一般我们登录系统时都是以普通账户的身份登录的，要创建用户需要 root 权限，这里就要用到 <code>sudo</code> 这个命令了。不过使用这个命令有两个大前提，一是你要知道当前登录用户的密码，二是当前用户必须在 <code>sudo</code> 用户组。shiyanlou 用户也属于 sudo 用户组（稍后会介绍如何查看和添加用户组）。</p>
<h4 id="su，su-与-sudo"><a href="#su，su-与-sudo" class="headerlink" title="su，su- 与 sudo"></a>su，su- 与 sudo</h4><p><strong>需要注意 Linux 环境下输入密码是不会显示的。</strong></p>
<p><code>su &lt;user&gt;</code> 可以切换到用户 user，执行时需要输入目标用户的密码，<code>sudo &lt;cmd&gt;</code> 可以以特权级别运行 cmd 命令，需要当前用户属于 sudo 组，且需要输入当前用户的密码。<code>su - &lt;user&gt;</code> 命令也是切换用户，但是同时用户的环境变量和工作目录也会跟着改变成目标用户所对应的。</p>
<p>现在我们新建一个叫 <code>lilei</code> 的用户：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo adduser lilei</span><br></pre></td></tr></table></figure>

<p>实验楼的环境目前设置为 shiyanlou 用户执行 sudo 不需要输入密码，通常此处需要按照提示输入 shiyanlou 密码（<strong>Linux 下密码输入是不显示任何内容的，shiyanlou 用户密码可以在右侧环境信息里查看，请勿自行设置密码</strong>）。然后是给 lilei 用户设置密码，后面的选项的一些内容你可以选择直接回车使用默认值。</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731216215.png" alt="3-2.2-1"></p>
<p>这个命令不但可以添加用户到系统，同时也会默认为新用户在 &#x2F;home 目录下创建一个工作目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls /home</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583141675216" alt="图片描述"></p>
<p>现在你已经创建好一个用户，并且你可以使用你创建的用户登录了，使用如下命令切换登录用户：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su -l lilei</span><br></pre></td></tr></table></figure>

<p>输入刚刚设置的 lilei 的密码，然后输入如下命令并查看输出：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">who am i</span><br><span class="line">whoami</span><br><span class="line">pwd</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583142076115" alt="图片描述"></p>
<p>你发现了区别了吗？这就是上一小节我们讲到的 <code>who am i</code> 和 <code>whoami</code> 命令的区别。</p>
<p>退出当前用户跟退出终端一样，可以使用 <code>exit</code> 命令或者使用快捷键 <code>Ctrl+D</code>。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583142261959" alt="图片描述"></p>
<h3 id="用户组"><a href="#用户组" class="headerlink" title="用户组"></a>用户组</h3><p>在 Linux 里面每个用户都有一个归属（用户组），用户组简单地理解就是一组用户的集合，它们共享一些资源和权限，同时拥有私有资源，就跟家的形式差不多，你的兄弟姐妹（不同的用户）属于同一个家（用户组），你们可以共同拥有这个家（共享资源），爸妈对待你们都一样（共享权限），你偶尔写写日记，其他人未经允许不能查看（私有资源和权限）。当然一个用户是可以属于多个用户组的，正如你既属于家庭，又属于学校或公司。</p>
<p>在 Linux 里面如何知道自己属于哪些用户组呢？</p>
<h4 id="方法一：使用-groups-命令"><a href="#方法一：使用-groups-命令" class="headerlink" title="方法一：使用 groups 命令"></a>方法一：使用 groups 命令</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">groups shiyanlou</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid13labid3timestamp1454035714557.png" alt="此处输入图片的描述"></p>
<p>其中冒号之前表示用户，后面表示该用户所属的用户组。这里可以看到 shiyanlou 用户属于 shiyanlou 用户组，每次新建用户如果不指定用户组的话，默认会自动创建一个与用户名相同的用户组（差不多就相当于家长的意思）。</p>
<p>默认情况下在 sudo 用户组里的可以使用 sudo 命令获得 root 权限。shiyanlou 用户也可以使用 sudo 命令，为什么这里没有显示在 sudo 用户组里呢？可以查看下 <code>/etc/sudoers.d/shiyanlou</code> 文件，我们在 <code>/etc/sudoers.d</code> 目录下创建了这个文件，从而给 shiyanlou 用户赋予了 sudo 权限：</p>
<p><img src="https://doc.shiyanlou.com/document-uid13labid3timestamp1454035855554.png" alt="此处输入图片的描述"></p>
<h4 id="方法二：查看-etc-group-文件"><a href="#方法二：查看-etc-group-文件" class="headerlink" title="方法二：查看 /etc/group 文件"></a>方法二：查看 <code>/etc/group</code> 文件</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/group | sort</span><br></pre></td></tr></table></figure>

<p>这里 <code>cat</code> 命令用于读取指定文件的内容并打印到终端输出，后面会详细讲它的使用。 <code>| sort</code> 表示将读取的文本进行一个字典排序再输出，然后你将看到如下一堆输出，你可以在最下面看到 shiyanlou 的用户组信息：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731335264.png" alt="3-2.3-3"></p>
<p>没找到？没关系，你可以使用 <code>grep</code> 命令过滤掉一些你不想看到的结果：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/group | grep -E &quot;shiyanlou&quot;</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid13labid3timestamp1454035698068.png" alt="此处输入图片的描述"></p>
<p><strong><code>/etc/group</code> 文件格式说明</strong></p>
<p>&#x2F;etc&#x2F;group 的内容包括用户组（Group）、用户组口令、GID（组 ID） 及该用户组所包含的用户（User），每个用户组一条记录。格式如下：</p>
<blockquote>
<p>group_name:password:GID:user_list</p>
</blockquote>
<p>你看到上面的 password 字段为一个 <code>x</code>，并不是说密码就是它，只是表示密码不可见而已。</p>
<p>这里需要注意，如果用户的 GID 等于用户组的 GID，那么最后一个字段 <code>user_list</code> 就是空的，这里的 GID 是指用户默认所在组的 GID，可以使用 <code>id</code> 命令查看。比如 shiyanlou 用户，在 <code>/etc/group</code> 中的 shiyanlou 用户组后面是不会显示的。lilei 用户，在 <code>/etc/group</code> 中的 lilei 用户组后面是不会显示的。</p>
<h4 id="将其它用户加入-sudo-用户组"><a href="#将其它用户加入-sudo-用户组" class="headerlink" title="将其它用户加入 sudo 用户组"></a>将其它用户加入 sudo 用户组</h4><p>默认情况下新创建的用户是不具有 root 权限的，也不在 sudo 用户组，可以让其加入 sudo 用户组从而获取 root 权限：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 注意 Linux 上输入密码是不会显示的</span><br><span class="line">su -l lilei</span><br><span class="line">sudo ls</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583145040679" alt="图片描述"></p>
<p>会提示 lilei 不在 sudoers 文件中，意思就是 lilei 不在 sudo 用户组中，至于 sudoers 文件（&#x2F;etc&#x2F;sudoers）你现在最好不要动它，操作不慎会导致比较麻烦的后果。</p>
<p>使用 <code>usermod</code> 命令可以为用户添加用户组，同样使用该命令你必需有 root 权限，你可以直接使用 root 用户为其它用户添加用户组，或者用其它已经在 sudo 用户组的用户使用 sudo 命令获取权限来执行该命令。</p>
<p>这里我用 shiyanlou 用户执行 sudo 命令将 lilei 添加到 sudo 用户组，让它也可以使用 sudo 命令获得 root 权限，首先我们切换回 shiyanlou 用户。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">su - shiyanlou</span><br></pre></td></tr></table></figure>

<p>此处需要输入 shiyanlou 用户密码，shiyanlou 的密码可以在右侧工具栏的环境信息里看到。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200616-1592274816723" alt="图片描述"></p>
<p>当然也可以通过 <code>sudo passwd shiyanlou</code> 进行设置，或者你直接关闭当前终端打开一个新的终端。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">groups lilei</span><br><span class="line">sudo usermod -G sudo lilei</span><br><span class="line">groups lilei</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583145514469" alt="图片描述"></p>
<p>然后你再切换回 lilei 用户，现在就可以使用 sudo 获取 root 权限了。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583145591124" alt="图片描述"></p>
<h3 id="删除用户和用户组"><a href="#删除用户和用户组" class="headerlink" title="删除用户和用户组"></a>删除用户和用户组</h3><p>删除用户是很简单的事：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo deluser lilei --remove-home</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid3timestamp1531731417990.png" alt="3-2.4-1"></p>
<p>使用 <code>--remove-home</code> 参数在删除用户时候会一并将该用户的工作目录一并删除。如果不使用那么系统会自动在 &#x2F;home 目录为该用户保留工作目录。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583146790310" alt="图片描述"></p>
<p>删除用户组可以使用 <code>groupdel</code> 命令，倘若该群组中仍包括某些用户，则必须先删除这些用户后，才能删除群组。</p>
<h2 id="Linux-文件权限"><a href="#Linux-文件权限" class="headerlink" title="Linux 文件权限"></a>Linux 文件权限</h2><p>文件权限就是文件的访问控制权限，即哪些用户和组群可以访问文件以及可以执行什么样的操作。</p>
<p>Unix&#x2F;Linux 系统是一个典型的多用户系统，不同的用户处于不同的地位，对文件和目录有不同的访问权限。为了保护系统的安全性，Unix&#x2F;Linux 系统除了对用户权限作了严格的界定外，还在用户身份认证、访问控制、传输安全、文件读写权限等方面作了周密的控制。</p>
<p>在 Unix&#x2F;Linux 中的每一个文件或目录都包含有访问权限，这些访问权限决定了谁能访问和如何访问这些文件和目录。</p>
<h3 id="查看文件权限"><a href="#查看文件权限" class="headerlink" title="查看文件权限"></a>查看文件权限</h3><p>我们之前已经很多次用到 <code>ls</code> 命令了，如你所见，我们用它来列出并显示当前目录下的文件，当然这是在不带任何参数的情况下，它能做的当然不止这么多，现在我们就要用它来查看文件权限。</p>
<p>使用较长格式列出文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -l</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583147815919" alt="图片描述">)</p>
<p>你可能除了知道最后面那一项是文件名之外，其它项就不太清楚了，那么到底是什么意思呢：</p>
<p><img src="https://doc.shiyanlou.com/linux_base/3-9.png" alt="pic"></p>
<p>可能你还是不太明白，比如第一项文件类型和权限那一堆东西具体指什么，链接又是什么，何为最后修改时间，下面一一道来：</p>
<p><img src="https://doc.shiyanlou.com/linux_base/3-10.png" alt="pic"></p>
<ul>
<li>文件类型</li>
</ul>
<p>关于文件类型，这里有一点你必需时刻牢记 <strong>Linux 里面一切皆文件</strong>，正因为这一点才有了设备文件（ <code>/dev</code> 目录下有各种设备文件，大都跟具体的硬件设备相关）这一说。 <code>socket</code>：网络套接字，具体是什么，感兴趣的用户可以去学习实验楼的后续相关课程。<code>pipe</code> 管道，这个东西很重要，我们以后将会讨论到，这里你先知道有它的存在即可。<code>软链接文件</code>：链接文件是分为两种的，另一种当然是“硬链接”（硬链接不常用，具体内容不作为本课程讨论重点，而软链接等同于 Windows 上的快捷方式，你记住这一点就够了）。</p>
<ul>
<li>文件权限</li>
</ul>
<p>读权限，表示你可以使用 <code>cat &lt;file name&gt;</code> 之类的命令来读取某个文件的内容；写权限，表示你可以编辑和修改某个文件的内容；</p>
<p>执行权限，通常指可以运行的二进制程序文件或者脚本文件，如同 Windows 上的 <code>exe</code> 后缀的文件，不过 Linux 上不是通过文件后缀名来区分文件的类型。你需要注意的一点是，<strong>一个目录同时具有读权限和执行权限才可以打开并查看内部文件，而一个目录要有写权限才允许在其中创建其它文件</strong>，这是因为目录文件实际保存着该目录里面的文件的列表等信息。</p>
<p>所有者权限，这一点相信你应该明白了，至于所属用户组权限，是指你所在的用户组中的所有其它用户对于该文件的权限，比如，你有一个 iPad，那么这个用户组权限就决定了你的兄弟姐妹有没有权限使用它破坏它和占有它。</p>
<ul>
<li>链接数</li>
</ul>
<blockquote>
<p>链接到该文件所在的 inode 结点的文件名数目（关于这个概念涉及到 Linux 文件系统的相关概念知识，不在本课程的讨论范围，感兴趣的用户可以查看 <a target="_blank" rel="noopener" href="https://www.ibm.com/developerworks/cn/linux/l-cn-hardandsymb-links/index.html#major2">硬链接和软链接的联系与区别</a>）。</p>
</blockquote>
<ul>
<li>文件大小</li>
</ul>
<blockquote>
<p>以 inode 结点大小为单位来表示的文件大小，你可以给 ls 加上 <code>-lh</code> 参数来更直观的查看文件的大小。</p>
</blockquote>
<p>明白了文件权限的一些概念，我们顺带补充一下关于 <code>ls</code> 命令的一些其它常用的用法：</p>
<ul>
<li>显示除了 <code>.</code>（当前目录）和 <code>..</code>（上一级目录）之外的所有文件，包括隐藏文件（Linux 下以 <code>.</code> 开头的文件为隐藏文件）。</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -a</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148438097" alt="图片描述">)</p>
<p>当然，你可以同时使用 <code>-a</code> 和 <code>-l</code> 参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -al</span><br></pre></td></tr></table></figure>

<p>查看某一个目录的完整属性，而不是显示目录里面的文件属性：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -dl &lt;目录名&gt;</span><br></pre></td></tr></table></figure>

<ul>
<li>显示所有文件大小，并以普通人类能看懂的方式呈现：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -asSh</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148552984" alt="图片描述"></p>
<p>其中小 s 为显示文件大小，大 S 为按文件大小排序，若需要知道如何按其它方式排序，可以使用 <code>man ls</code> 命令查询。</p>
<h3 id="变更文件所有者"><a href="#变更文件所有者" class="headerlink" title="变更文件所有者"></a>变更文件所有者</h3><blockquote>
<p>若前面已经执行删除 lilei 用户的命令，这里重新创建一下。</p>
</blockquote>
<p>切换到 lilei 用户，然后在 &#x2F;home&#x2F;lilei 目录新建一个文件，命名为 <code>iphone11</code>。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">su - lilei</span><br><span class="line">pwd</span><br><span class="line">touch iphone11</span><br><span class="line">ls -alh iphone11</span><br></pre></td></tr></table></figure>

<p>可见文件所有者是 lilei ：</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148845314" alt="图片描述"></p>
<p>现在切换回到 shiyanlou 用户，使用以下命令变更文件所有者为 shiyanlou。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 需要切换到 shiyanlou 用户执行以下操作</span><br><span class="line">cd /home/lilei</span><br><span class="line">ls iphone11</span><br><span class="line">sudo chown shiyanlou iphone11</span><br></pre></td></tr></table></figure>

<p>现在查看，发现文件所有者成功修改为 shiyanlou。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583148964757" alt="图片描述">)</p>
<h3 id="修改文件权限"><a href="#修改文件权限" class="headerlink" title="修改文件权限"></a>修改文件权限</h3><p>如果你有一个自己的文件不想被其他用户读、写、执行，那么就需要对文件的权限做修改。文件的权限有两种表示方式：</p>
<ul>
<li>方式一：二进制数字表示</li>
</ul>
<p><img src="https://doc.shiyanlou.com/linux_base/3-14.png" alt="pic"></p>
<p>每个文件有三组固定的权限，分别对应拥有者，所属用户组，其他用户，<strong>记住这个顺序是固定的</strong>。文件的读写执行对应字母 <code>rwx</code>，以二进制表示就是 <code>111</code>，用十进制表示就是 <code>7</code>，对进制转换不熟悉的同学可以看看 <a target="_blank" rel="noopener" href="https://baike.baidu.com/item/%E8%BF%9B%E5%88%B6%E8%BD%AC%E6%8D%A2/3117222">进制转换</a>。例如我们刚刚新建的文件 iphone11 的权限是 <code>rw-rw-rw-</code>，换成对应的十进制表示就是 666，这就表示这个文件的拥有者，所属用户组和其他用户具有读写权限，不具有执行权限。</p>
<p>如果我要将文件 <code>iphone11</code> 的权限改为只有我自己可以用那么就可以用这个方法更改它的权限。</p>
<p>为了演示，我先在文件里加点内容：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;echo \&quot;hello shiyanlou\&quot;&quot; &gt; iphone11</span><br></pre></td></tr></table></figure>

<p>然后修改权限：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">chmod 600 iphone11</span><br><span class="line">ls -alh iphone11</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583149616295" alt="图片描述"></p>
<p>切换到 lilei 用户，尝试写入和读取操作，可以看到 lilei 用户已经不能读写这个 iphone11 文件了：</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583149700161" alt="图片描述"></p>
<ul>
<li>方式二：加减赋值操作</li>
</ul>
<p>要完成上述实验相同的效果，你可以：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod go-rw iphone11</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200302-1583150177369" alt="图片描述"></p>
<p><code>g</code>、<code>o</code> 还有 <code>u</code> 分别表示 group（用户组）、others（其他用户） 和 user（用户），<code>+</code> 和 <code>-</code> 分别表示增加和去掉相应的权限。</p>
<h2 id="更多"><a href="#更多" class="headerlink" title="更多"></a>更多</h2><p><strong><code>adduser</code> 和 <code>useradd</code> 的区别是什么</strong></p>
<p>答：<code>useradd</code> 只创建用户，不会创建用户密码和工作目录，创建完了需要使用 <code>passwd &lt;username&gt;</code> 去设置新用户的密码。<code>adduser</code> 在创建用户的同时，会创建工作目录和密码（提示你设置），做这一系列的操作。其实 <code>useradd</code>、<code>userdel</code> 这类操作更像是一种命令，执行完了就返回。而 <code>adduser</code> 更像是一种程序，需要你输入、确定等一系列操作。</p>
<h1 id="Linux目录结构及文件基本操作"><a href="#Linux目录结构及文件基本操作" class="headerlink" title="Linux目录结构及文件基本操作"></a>Linux目录结构及文件基本操作</h1><h2 id="Linux目录结构"><a href="#Linux目录结构" class="headerlink" title="Linux目录结构"></a>Linux目录结构</h2><h3 id="FHS-标准"><a href="#FHS-标准" class="headerlink" title="FHS 标准"></a>FHS 标准</h3><p>Linux 的目录结构说复杂很复杂，说简单也很简单。复杂在于，因为系统的正常运行是以目录结构为基础的，对于初学者来说里面大部分目录都不知道其作用，重要与否，特别对于那些曾经的重度 Windows 用户，他们会纠结很长时间，关于我安装的软件在哪里这类问题。说它简单是因为，其中大部分目录结构是规定好了的（FHS 标准），是死的，当你掌握后，你在里面的一切操作都会变得井然有序。</p>
<blockquote>
<p>FHS（英文：Filesystem Hierarchy Standard 中文：文件系统层次结构标准），多数 Linux 版本采用这种文件组织形式，FHS 定义了系统中每个区域的用途、所需要的最小构成的文件和目录同时还给出了例外处理与矛盾处理。</p>
</blockquote>
<p>FHS 定义了两层规范，第一层是， <code>/</code> 下面的各个目录应该要放什么文件数据，例如 <code>/etc</code> 应该放置设置文件，<code>/bin</code> 与 <code>/sbin</code> 则应该放置可执行文件等等。</p>
<p>第二层则是针对 <code>/usr</code> 及 <code>/var</code> 这两个目录的子目录来定义。例如 <code>/var/log</code> 放置系统日志文件，<code>/usr/share</code> 放置共享数据等等。</p>
<p><a target="_blank" rel="noopener" href="https://refspecs.linuxfoundation.org/FHS_3.0/fhs-3.0.pdf">FHS_3.0 标准文档</a></p>
<p><strong>如果觉得图片不清晰，建议另存为到本地放大查看：</strong></p>
<p><img src="https://doc.shiyanlou.com/linux_base/4-1.png" alt="img"></p>
<p>如果你觉得看这个不明白，那么可以试试最真实最直观的方式，执行如下命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tree /</span><br></pre></td></tr></table></figure>

<p>如果提示” command not found “，就先安装：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 因为我们的环境的原因，每次新启动实验会清除系统恢复到初始状态，所以需要手动更新软件包索引，以便我们安装时能找到相应软件包的源。</span><br><span class="line"></span><br><span class="line">sudo apt-get update</span><br><span class="line"></span><br><span class="line">sudo apt-get install tree</span><br></pre></td></tr></table></figure>

<p>关于上面提到的 FHS，这里还有个很重要的内容你一定要明白，FHS 是根据以往无数 Linux 用户和开发者的经验总结出来的，并且会维持更新，FHS 依据文件系统使用的频繁与否以及是否允许用户随意改动（注意，不是不能，学习过程中，不要怕这些），将目录定义为四种交互作用的形态，如下表所示：</p>
<p><img src="https://doc.shiyanlou.com/document-uid18510labid59timestamp1482919171956.png" alt="此处输入图片的描述"></p>
<h3 id="目录路径"><a href="#目录路径" class="headerlink" title="目录路径"></a>目录路径</h3><h4 id="路径"><a href="#路径" class="headerlink" title="路径"></a>路径</h4><p>有人可能不明白这路径是指什么，有什么用。顾名思义，路径就是你要去哪儿的路线嘛。如果你想进入某个具体的目录或者想获得某个目录的文件（目录本身也是文件）那就得用路径来找到了。</p>
<p>使用 <code>cd</code> 命令可以切换目录，在 Linux 里面使用 <code>.</code> 表示当前目录，<code>..</code> 表示上一级目录（<strong>注意，我们上一节介绍过的，以 . 开头的文件都是隐藏文件，所以这两个目录必然也是隐藏的，你可以使用 ls -a 命令查看隐藏文件</strong>），<code>-</code> 表示上一次所在目录，<code>～</code> 通常表示当前用户的 <code>home</code> 目录。使用 <code>pwd</code> 命令可以获取当前所在路径（绝对路径）。</p>
<p>进入上一级目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd ..</span><br></pre></td></tr></table></figure>

<p>进入你的 <code>home</code> 目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd ~</span><br><span class="line"># 或者 cd /home/&lt;你的用户名&gt;</span><br></pre></td></tr></table></figure>

<p>有的同学可能会有疑问，为什么环境中的波浪号 ~ 在上面，而有些环境在中间。这主要是不同的字体导致的。比如我们环境中默认使用的 <code>Monospace</code> 字体，波浪号就在最上方。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583207588297" alt="图片描述"></p>
<p>我们可以在首选项里面切换到其他字体，可以看到该字体的波浪号默认是中间的。当然，这个并不影响我们操作。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583207655389" alt="图片描述"></p>
<p>使用 <code>pwd</code> 获取当前路径：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pwd</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733883613.png" alt="4-2.2-1"></p>
<h4 id="绝对路径"><a href="#绝对路径" class="headerlink" title="绝对路径"></a>绝对路径</h4><p>关于绝对路径，简单地说就是以根” &#x2F; “目录为起点的完整路径，以你所要到的目录为终点，表现形式如： <code>/usr/local/bin</code>，表示根目录下的 <code>usr</code> 目录中的 <code>local</code> 目录中的 <code>bin</code> 目录。</p>
<h4 id="相对路径"><a href="#相对路径" class="headerlink" title="相对路径"></a>相对路径</h4><p>相对路径，也就是相对于你当前的目录的路径，相对路径是以当前目录 <code>.</code> 为起点，以你所要到的目录为终点，表现形式如： <code>usr/local/bin</code> （这里假设你当前目录为根目录）。你可能注意到，我们表示相对路径实际并没有加上表示当前目录的那个 <code>.</code> ，而是直接以目录名开头，因为这个 <code>usr</code> 目录为 <code>/</code> 目录下的子目录，是可以省略这个 <code>.</code> 的（以后会讲到一个类似不能省略的情况）；如果是当前目录的上一级目录，则需要使用 <code>..</code> ，比如你当前目录为 <code>/home/shiyanlou</code> 目录下，根目录就应该表示为 <code>../../</code> ，表示上一级目录（ <code>home</code> 目录）的上一级目录（ <code>/</code> 目录）。</p>
<p>下面我们以你的 <code>home</code> 目录为起点，分别以绝对路径和相对路径的方式进入 <code>/usr/local/bin</code> 目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 绝对路径</span><br><span class="line">cd /usr/local/bin</span><br><span class="line"># 相对路径</span><br><span class="line">cd ../../usr/local/bin</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733900438.png" alt="4-2.2-2"></p>
<p>进入一个目录，可以使用绝对路径也可以使用相对路径，那我们应该在什么时候选择正确的方式进入某个目录呢。就是凭直觉嘛，你觉得怎样方便就使用哪一个，而不用特意只使用某一种。比如假设我当前在 <code>/usr/local/bin</code> 目录，我想进入上一级的 local 目录你说是使用 <code>cd ..</code> 方便还是 <code>cd /usr/local</code> 方便？而如果要进入的是 <code>usr</code> 目录，那么 <code>cd /usr</code> ，就比 <code>cd ../..</code> 方便一点了。</p>
<p><strong>提示：在进行目录切换的过程中请多使用 Tab 键自动补全，可避免输入错误，连续按两次 Tab 可以显示全部候选结果。</strong></p>
<h2 id="Linux文件的基本操作"><a href="#Linux文件的基本操作" class="headerlink" title="Linux文件的基本操作"></a>Linux文件的基本操作</h2><h3 id="新建"><a href="#新建" class="headerlink" title="新建"></a>新建</h3><h4 id="新建空白文件"><a href="#新建空白文件" class="headerlink" title="新建空白文件"></a>新建空白文件</h4><p>使用 <code>touch</code> 命令创建空白文件，关于 <code>touch</code> 命令，其主要作用是来更改已有文件的时间戳的（比如，最近访问时间，最近修改时间），但其在不加任何参数的情况下，只指定一个文件名，则可以创建一个指定文件名的空白文件（不会覆盖已有同名文件），当然你也可以同时指定该文件的时间戳，更多关于 <code>touch</code> 命令的用法，会在下一讲文件搜索中涉及。</p>
<p>创建名为 test 的空白文件，因为在其它目录没有权限，所以需要先 <code>cd ~</code> 切换回 shiyanlou 用户的 Home 目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd ~</span><br><span class="line">touch test</span><br></pre></td></tr></table></figure>

<h4 id="新建目录"><a href="#新建目录" class="headerlink" title="新建目录"></a>新建目录</h4><p>使用 <code>mkdir</code>（make directories）命令可以创建一个空目录，也可同时指定创建目录的权限属性。</p>
<p>创建名为“ mydir ”的空目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir mydir</span><br></pre></td></tr></table></figure>

<p>使用 <code>-p</code> 参数，同时创建父目录（如果不存在该父目录），如下我们同时创建一个多级目录（这在安装软件、配置安装路径时非常有用）：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p father/son/grandson</span><br></pre></td></tr></table></figure>

<p>这里使用的路径是相对路径，代表在当前目录下生成，当然我们直接以绝对路径的方式表示也是可以的。</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733939312.png" alt="4-3.1-1"></p>
<p>还有一点需要注意的是，若当前目录已经创建了一个 test 文件，再使用 <code>mkdir test</code> 新建同名的文件夹，系统会报错文件已存在。这符合 Linux 一切皆文件的理念。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583209669773" alt="图片描述"></p>
<p>若当前目录存在一个 test 文件夹，则 <code>touch</code> 命令，则会更改该文件夹的时间戳而不是新建文件。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583210207550" alt="图片描述"></p>
<h3 id="复制"><a href="#复制" class="headerlink" title="复制"></a>复制</h3><h4 id="复制文件"><a href="#复制文件" class="headerlink" title="复制文件"></a>复制文件</h4><p>使用 <code>cp</code> 命令（copy）复制一个文件到指定目录。</p>
<p>将之前创建的 <code>test</code> 文件复制到 <code>/home/shiyanlou/father/son/grandson</code> 目录中：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cp test father/son/grandson</span><br></pre></td></tr></table></figure>

<p>是不是很方便啊，如果在图形界面则需要先在源目录复制文件，再进到目的目录粘贴文件，而命令行操作步骤就一步到位了嘛。</p>
<h4 id="复制目录"><a href="#复制目录" class="headerlink" title="复制目录"></a>复制目录</h4><p>如果直接使用 <code>cp</code> 命令复制一个目录的话，会出现如下错误：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733966731.png" alt="4-3.1-2"></p>
<p>要成功复制目录需要加上 <code>-r</code> 或者 <code>-R</code> 参数，表示递归复制，就是说有点“株连九族”的意思：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">mkdir family</span><br><span class="line">cp -r father family</span><br></pre></td></tr></table></figure>

<h3 id="删除"><a href="#删除" class="headerlink" title="删除"></a>删除</h3><h4 id="删除文件"><a href="#删除文件" class="headerlink" title="删除文件"></a>删除文件</h4><p>使用 <code>rm</code>（remove files or directories）命令删除一个文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm test</span><br></pre></td></tr></table></figure>

<p>有时候你会遇到想要删除一些为只读权限的文件，直接使用 <code>rm</code> 删除会显示一个提示，如下：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531733991692.png" alt="4-3.3-1"></p>
<p>你如果想忽略这提示，直接删除文件，可以使用 <code>-f</code> 参数强制删除：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -f test</span><br></pre></td></tr></table></figure>

<h4 id="删除目录"><a href="#删除目录" class="headerlink" title="删除目录"></a>删除目录</h4><p>跟复制目录一样，要删除一个目录，也需要加上 <code>-r</code> 或 <code>-R</code> 参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -r family</span><br></pre></td></tr></table></figure>

<p>遇到权限不足删除不了的目录也可以和删除文件一样加上 <code>-f</code> 参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rm -rf family</span><br></pre></td></tr></table></figure>

<h3 id="移动文件与文件重命名"><a href="#移动文件与文件重命名" class="headerlink" title="移动文件与文件重命名"></a>移动文件与文件重命名</h3><p> 移动文件</p>
<p>使用 <code>mv</code>（move or rename files）命令移动文件（剪切）。命令格式是 <code>mv 源目录文件 目的目录</code>。</p>
<p>例如将文件“ file1 ”移动到 <code>Documents</code> 目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir Documents</span><br><span class="line">touch file1</span><br><span class="line">mv file1 Documents</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734147663.png" alt="4-3.4-1"></p>
<h4 id="重命名文件"><a href="#重命名文件" class="headerlink" title="重命名文件"></a>重命名文件</h4><p><code>mv</code> 命令除了能移动文件外，还能给文件重命名。命令格式为 <code>mv 旧的文件名 新的文件名</code>。</p>
<p>例如将文件“ file1 ”重命名为“ myfile ”：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mv file1 myfile</span><br></pre></td></tr></table></figure>

<h4 id="批量重命名"><a href="#批量重命名" class="headerlink" title="批量重命名"></a>批量重命名</h4><p>要实现批量重命名，<code>mv</code> 命令就有点力不从心了，我们可以使用一个看起来更专业的命令 <code>rename</code> 来实现。不过它要用 perl 正则表达式来作为参数，关于正则表达式我们要在后面才会介绍到，这里只做演示，你只要记得这个 <code>rename</code> 命令可以批量重命名就好了，以后再重新学习也不会有任何问题，毕竟你已经掌握了一个更常用的 <code>mv</code> 命令。</p>
<p><code>rename</code> 命令并不是内置命令，若提示无该命令可以使用 <code>sudo apt-get install rename</code> 命令自行安装。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou/</span><br><span class="line"></span><br><span class="line"># 使用通配符批量创建 5 个文件:</span><br><span class="line">touch file&#123;1..5&#125;.txt</span><br><span class="line"></span><br><span class="line"># 批量将这 5 个后缀为 .txt 的文本文件重命名为以 .c 为后缀的文件:</span><br><span class="line">rename &#x27;s/\.txt/\.c/&#x27; *.txt</span><br><span class="line"></span><br><span class="line"># 批量将这 5 个文件，文件名和后缀改为大写:</span><br><span class="line">rename &#x27;y/a-z/A-Z/&#x27; *.c</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583213792916" alt="图片描述"></p>
<p>简单解释一下上面的命令，<code>rename</code> 是先使用第二个参数的通配符匹配所有后缀为 <code>.txt</code> 的文件，然后使用第一个参数提供的正则表达式将匹配的这些文件的 <code>.txt</code> 后缀替换为 <code>.c</code>，这一点在我们后面学习了 <code>sed</code> 命令后，相信你会更好地理解。</p>
<p>有的同学可能在输入时出现命令未闭合的状态，命令行会出现 <code>quote&gt;</code> 开头的提示符。这是因为上述命令中的 <code>&#39;</code> 未输入完成，这时按下 ctrl+c 即可退出该模式。还有就是注意 <code>&#39;</code> 必须为英文符号（半角），若输入的是中文符号（全角）也会报错。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583213884277" alt="图片描述"></p>
<h3 id="查看文件"><a href="#查看文件" class="headerlink" title="查看文件"></a>查看文件</h3><h4 id="使用-cat，tac-和-nl-命令查看文件"><a href="#使用-cat，tac-和-nl-命令查看文件" class="headerlink" title="使用 cat，tac 和 nl 命令查看文件"></a>使用 <code>cat</code>，<code>tac</code> 和 <code>nl</code> 命令查看文件</h4><p>前两个命令都是用来打印文件内容到标准输出（终端），其中 <code>cat</code> 为正序显示，<code>tac</code> 为倒序显示。</p>
<blockquote>
<p>标准输入输出：当我们执行一个 shell 命令行时通常会自动打开三个标准文件，即标准输入文件（stdin），默认对应终端的键盘、标准输出文件（stdout）和标准错误输出文件（stderr），后两个文件都对应被重定向到终端的屏幕，以便我们能直接看到输出内容。进程将从标准输入文件中得到输入数据，将正常输出数据输出到标准输出文件，而将错误信息送到标准错误文件中。</p>
</blockquote>
<p>比如我们要查看之前从 <code>/etc</code> 目录下拷贝来的 <code>passwd</code> 文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">cp /etc/passwd passwd</span><br><span class="line">cat passwd</span><br></pre></td></tr></table></figure>

<p>可以加上 <code>-n</code> 参数显示行号：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat -n passwd</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734168883.png" alt="4-3.4-1"></p>
<p><code>nl</code> 命令，添加行号并打印，这是个比 <code>cat -n</code> 更专业的行号打印命令。</p>
<p>这里简单列举它的常用的几个参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">-b : 指定添加行号的方式，主要有两种：</span><br><span class="line">    -b a:表示无论是否为空行，同样列出行号(&quot;cat -n&quot;就是这种方式)</span><br><span class="line">    -b t:只列出非空行的编号并列出（默认为这种方式）</span><br><span class="line">-n : 设置行号的样式，主要有三种：</span><br><span class="line">    -n ln:在行号字段最左端显示</span><br><span class="line">    -n rn:在行号字段最右边显示，且不加 0</span><br><span class="line">    -n rz:在行号字段最右边显示，且加 0</span><br><span class="line">-w : 行号字段占用的位数(默认为 6 位)</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734186668.png" alt="4-3.5-2"></p>
<p>你会发现使用这几个命令，默认的终端窗口大小，一屏显示不完文本的内容，得用鼠标拖动滚动条或者滑动滚轮才能继续往下翻页，要是可以直接使用键盘操作翻页就好了，那么你就可以使用下面要介绍的命令。</p>
<h4 id="使用-more-和-less-命令分页查看文件"><a href="#使用-more-和-less-命令分页查看文件" class="headerlink" title="使用 more 和 less 命令分页查看文件"></a>使用 <code>more</code> 和 <code>less</code> 命令分页查看文件</h4><p>如果说上面的 <code>cat</code> 是用来快速查看一个文件的内容的，那么这个 <code>more</code> 和 <code>less</code> 就是天生用来”阅读”一个文件的内容的，比如说 man 手册内部就是使用的 <code>less</code> 来显示内容。其中 <code>more</code> 命令比较简单，只能向一个方向滚动，而 <code>less</code> 为基于 <code>more</code> 和 <code>vi</code> （一个强大的编辑器，我们有单独的课程来让你学习）开发，功能更强大。<code>less</code> 的使用基本和 <code>more</code> 一致，具体使用请查看 man 手册，这里只介绍 <code>more</code> 命令的使用。</p>
<p>使用 <code>more</code> 命令打开 <code>passwd</code> 文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">more passwd</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734202525.png" alt="4-3.5-3"></p>
<p>打开后默认只显示一屏内容，终端底部显示当前阅读的进度。可以使用 <code>Enter</code> 键向下滚动一行，使用 <code>Space</code> 键向下滚动一屏，按下 <code>h</code> 显示帮助，<code>q</code> 退出。</p>
<h4 id="使用-head-和-tail-命令查看文件"><a href="#使用-head-和-tail-命令查看文件" class="headerlink" title="使用 head 和 tail 命令查看文件"></a>使用 <code>head</code> 和 <code>tail</code> 命令查看文件</h4><p>这两个命令，那些性子比较急的人应该会喜欢，因为它们一个是只查看文件的头几行（默认为 10 行，不足 10 行则显示全部）和尾几行。还是拿 passwd 文件举例，比如当我们想要查看最近新增加的用户，那么我们可以查看这个 <code>/etc/passwd</code> 文件，不过我们前面也看到了，这个文件里面一大堆乱糟糟的东西，看起来实在费神啊。因为系统新增加一个用户，会将用户的信息添加到 passwd 文件的最后，那么这时候我们就可以使用 <code>tail</code> 命令了：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tail /etc/passwd</span><br></pre></td></tr></table></figure>

<p>甚至更直接的只看一行， 加上 <code>-n</code> 参数，后面紧跟行数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tail -n 1 /etc/passwd</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734226305.png" alt="4-3.5-4"></p>
<p>关于 <code>tail</code> 命令，不得不提的还有它一个很牛的参数 <code>-f</code>，这个参数可以实现不停地读取某个文件的内容并显示。这可以让我们动态查看日志，达到实时监视的目的。不过我不会在这门基础课程中介绍它的更多细节，感兴趣的用户可以自己去了解。</p>
<h3 id="查看文件类型"><a href="#查看文件类型" class="headerlink" title="查看文件类型"></a>查看文件类型</h3><p>我们可以使用 <code>file</code> 命令查看文件的类型：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">file /bin/ls</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid59timestamp1531734243413.png" alt="4-3.6-1"></p>
<p>说明这是一个可执行文件，运行在 64 位平台，并使用了动态链接文件（共享库）。</p>
<p>与 Windows 不同的是，如果你新建了一个 shiyanlou.txt 文件，Windows 会自动把它识别为文本文件，而 <code>file</code> 命令会识别为一个空文件。这个前面我提到过，在 Linux 中文件的类型不是根据文件后缀来判断的。当你在文件里输入内容后才会显示文件类型。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583215158345" alt="图片描述"></p>
<h3 id="编辑文件"><a href="#编辑文件" class="headerlink" title="编辑文件"></a>编辑文件</h3><p>在 Linux 下面编辑文件通常我们会直接使用专门的命令行编辑器比如（emacs，vim，nano），由于涉及 Linux 上的编辑器的内容比较多，且非常重要，故我们有一门单独的基础课专门介绍这中一个编辑器 vim 。</p>
<blockquote>
<p>强烈建议正在学习这门 Linux 基础课的你先在这里暂停一下，去学习 <a target="_blank" rel="noopener" href="https://www.lanqiao.cn/courses/2">vim 编辑器</a>的使用（至少掌握基本的操作），然后再继续本课程后面的内容，因为后面的内容会假设你已经学会了 vim 编辑器的使用。</p>
</blockquote>
<p>如果你想更加快速地入门，可以直接使用 Linux 内部的 vim 学习教程，输入如下命令即可开始：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vimtutor</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583215559370" alt="图片描述"> </p>
<h1 id="环境变量与文件查找"><a href="#环境变量与文件查找" class="headerlink" title="环境变量与文件查找"></a>环境变量与文件查找</h1><h2 id="环境变量"><a href="#环境变量" class="headerlink" title="环境变量"></a>环境变量</h2><p><strong>变量</strong></p>
<p>要解释环境变量，得先明白变量是什么，准确的说应该是 Shell 变量，所谓变量就是计算机中用于记录一个值（不一定是数值，也可以是字符或字符串）的符号，而这些符号将用于不同的运算处理中。通常变量与值是一对一的关系，可以通过表达式读取它的值并赋值给其它变量，也可以直接指定数值赋值给任意变量。为了便于运算和处理，大部分的编程语言会区分变量的类型，用于分别记录数值、字符或者字符串等等数据类型。Shell 中的变量也基本如此，有不同类型（但不用专门指定类型名），可以参与运算，有作用域限定。</p>
<blockquote>
<p>变量的作用域即变量的有效范围（比如一个函数中、一个源文件中或者全局范围），在该范围内只能有一个同名变量。一旦离开则该变量无效，如同不存在这个变量一般。</p>
</blockquote>
<p>在 Shell 中如何创建一个变量，如何给变量赋值和如何读取变量的值呢？这部分内容会在 <a target="_blank" rel="noopener" href="https://www.lanqiao.cn/courses/944">高级 bash 脚本编程指南</a> 这门课中详细介绍，这里我简单举例说明一下：</p>
<p>使用 <code>declare</code> 命令创建一个变量名为 tmp 的变量：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">declare tmp</span><br></pre></td></tr></table></figure>

<blockquote>
<p>其实也可以不用 declare 预声明一个变量，直接即用即创建，这里只是告诉你 declare 的作用，这在创建其它指定类型的变量（如数组）时会用到。</p>
</blockquote>
<p>使用 <code>=</code> 号赋值运算符，将变量 tmp 赋值为 shiyanlou。注意，与其他语言不同的是， Shell 中的赋值操作，<code>=</code> 两边不可以输入空格，否则会报错。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 正确的赋值</span><br><span class="line">tmp=shiyanlou</span><br><span class="line"></span><br><span class="line"># 错误的赋值</span><br><span class="line">tmp = shiyanlou</span><br></pre></td></tr></table></figure>

<p>读取变量的值，使用 <code>echo</code> 命令和 <code>$</code> 符号（**$ 符号用于表示引用一个变量的值，初学者经常忘记输入**）：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo $tmp</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339240610.png" alt="此处输入图片的描述"></p>
<p><strong>注意：并不是任何形式的变量名都是可用的，变量名只能是英文字母、数字或者下划线，且不能以数字作为开头。</strong></p>
<h3 id="环境变量-1"><a href="#环境变量-1" class="headerlink" title="环境变量"></a>环境变量</h3><p>简单理解了变量的概念，就很容易理解环境变量了。环境变量的作用域比自定义变量的要大，如 Shell 的环境变量作用于自身和它的子进程。在所有的 UNIX 和类 UNIX 系统中，每个进程都有其各自的环境变量设置，且默认情况下，当一个进程被创建时，除了创建过程中明确指定的话，它将继承其父进程的绝大部分环境设置。Shell 程序也作为一个进程运行在操作系统之上，而我们在 Shell 中运行的大部分命令都将以 Shell 的子进程的方式运行。</p>
<p><img src="https://doc.shiyanlou.com/linux_base/5-2.png" alt="1"></p>
<p>通常我们会涉及到的变量类型有三种：</p>
<ul>
<li>当前 Shell 进程私有用户自定义变量，如上面我们创建的 tmp 变量，只在当前 Shell 中有效。</li>
<li>Shell 本身内建的变量。</li>
<li>从自定义变量导出的环境变量。</li>
</ul>
<p>也有三个与上述三种环境变量相关的命令：<code>set</code>，<code>env</code>，<code>export</code>。这三个命令很相似，都是用于打印环境变量信息，区别在于涉及的变量范围不同。详见下表：</p>
<table>
<thead>
<tr>
<th>命 令</th>
<th>说 明</th>
</tr>
</thead>
<tbody><tr>
<td><code>set</code></td>
<td>显示当前 Shell 所有变量，包括其内建环境变量（与 Shell 外观等相关），用户自定义变量及导出的环境变量。</td>
</tr>
<tr>
<td><code>env</code></td>
<td>显示与当前用户相关的环境变量，还可以让命令在指定环境中运行。</td>
</tr>
<tr>
<td><code>export</code></td>
<td>显示从 Shell 中导出成环境变量的变量，也能通过它将自定义变量导出为环境变量。</td>
</tr>
</tbody></table>
<p><img src="https://doc.shiyanlou.com/linux_base/5-3.png" alt="1"></p>
<p>你可以更直观的使用 <code>vimdiff</code> 工具比较一下它们之间的差别：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">temp=shiyanlou</span><br><span class="line">export temp_env=shiyanlou</span><br><span class="line">env|sort&gt;env.txt</span><br><span class="line">export|sort&gt;export.txt</span><br><span class="line">set|sort&gt;set.txt</span><br></pre></td></tr></table></figure>

<p>上述操作将命令输出通过管道 <code>|</code> 使用 <code>sort</code> 命令排序，再重定向到对象文本文件中。管道的概念后面我们会学到，现在你知道这是什么意思就行了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vimdiff env.txt export.txt set.txt</span><br></pre></td></tr></table></figure>

<p>使用 <code>vimdiff</code> 工具比较导出的几个文件的内容，退出 <code>vimdiff</code> 需要按下 Esc 后输入 <code>:q</code> 即可退出。</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339264870.png" alt="1"></p>
<p>关于哪些变量是环境变量，可以简单地理解成在当前进程的子进程有效则为环境变量，否则不是（有些人也将所有变量统称为环境变量，只是以全局环境变量和局部环境变量进行区分，我们只要理解它们的实质区别即可）。我们这里用 <code>export</code> 命令来体会一下，先在 Shell 中设置一个变量 <code>temp=shiyanlou</code>，然后再新创建一个子 Shell 查看 <code>temp</code> 变量的值：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339293501.png" alt="此处输入图片的描述"></p>
<p><strong>注意：为了与普通变量区分，通常我们习惯将环境变量名设为大写。</strong></p>
<h4 id="永久生效"><a href="#永久生效" class="headerlink" title="永久生效"></a>永久生效</h4><p>但是问题来了，当你关机后，或者关闭当前的 shell 之后，环境变量就没了啊。怎么才能让环境变量永久生效呢？</p>
<p>按变量的生存周期来划分，Linux 变量可分为两类：</p>
<ol>
<li>永久的：需要修改配置文件，变量永久生效；</li>
<li>临时的：使用 export 命令行声明即可，变量在关闭 shell 时失效。</li>
</ol>
<p>这里介绍两个重要文件 <code>/etc/bashrc</code>（有的 Linux 没有这个文件） 和 <code>/etc/profile</code> ，它们分别存放的是 shell 变量和环境变量。还有要注意区别的是每个用户目录下的一个隐藏文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># .profile 可以用 ls -a 查看</span><br><span class="line">cd /home/shiyanlou</span><br><span class="line">ls -a</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583220161661" alt="图片描述"></p>
<p>这个 .profile 只对当前用户永久生效。因为它保存在当前用户的 Home 目录下，当切换用户时，工作目录可能一并被切换到对应的目录中，这个文件就无法生效。而写在 <code>/etc/profile</code> 里面的是对所有用户永久生效，所以如果想要添加一个永久生效的环境变量，只需要打开 <code>/etc/profile</code>，在最后加上你想添加的环境变量就好啦。</p>
<h3 id="命令的查找路径与顺序"><a href="#命令的查找路径与顺序" class="headerlink" title="命令的查找路径与顺序"></a>命令的查找路径与顺序</h3><p>你可能很早之前就有疑问，我们在 Shell 中输入一个命令，Shell 是怎么知道去哪找到这个命令然后执行的呢？这是通过环境变量 <code>PATH</code> 来进行搜索的，熟悉 Windows 的用户可能知道 Windows 中的也是有这么一个 PATH 环境变量。这个 <code>PATH</code> 里面就保存了 Shell 中执行的命令的搜索路径。</p>
<p>查看 <code>PATH</code> 环境变量的内容：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo $PATH</span><br></pre></td></tr></table></figure>

<p>默认情况下你会看到如下输出：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games</span><br></pre></td></tr></table></figure>

<p>如果你还记得 Linux 目录结构那一节的内容，你就应该知道上面这些目录下放的是哪一类文件了。通常这一类目录下放的都是可执行文件，当我们在 Shell 中执行一个命令时，系统就会按照 PATH 中设定的路径按照顺序依次到目录中去查找，如果存在同名的命令，则执行先找到的那个。</p>
<blockquote>
<p>下面我们将练习创建一个最简单的可执行 Shell 脚本和一个使用 C 语言创建的“ hello world ”程序，如果这两部分内容你之前没有学习过，那么你可以进行一个入门学习：</p>
</blockquote>
<ul>
<li><a target="_blank" rel="noopener" href="https://www.lanqiao.cn/courses/57">C 语言入门教程</a></li>
<li><a target="_blank" rel="noopener" href="https://www.lanqiao.cn/courses/5">高级 Bash 脚本编程指南</a></li>
<li><a target="_blank" rel="noopener" href="http://bash.cyberciti.biz/guide/Main_Page">Linux Shell Scripting Tutorial (LSST) v2.0</a></li>
</ul>
<p>创建一个 Shell 脚本文件，你可以使用 gedit，vim，sublime 等工具编辑。如果你是直接复制的话，建议使用 gedit 或者 sublime，否则可能导致代码缩进混乱。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">touch hello_shell.sh</span><br><span class="line">gedit hello_shell.sh</span><br></pre></td></tr></table></figure>

<p>在脚本中添加如下内容，保存并退出。</p>
<p><strong>注意不要省掉第一行，这不是注释，有用户反映有语法错误，就是因为没有了第一行。</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">#!/bin/bash</span><br><span class="line"></span><br><span class="line">for ((i=0; i&lt;10; i++));do</span><br><span class="line">    echo &quot;hello shell&quot;</span><br><span class="line">done</span><br><span class="line"></span><br><span class="line">exit 0</span><br></pre></td></tr></table></figure>

<p>为文件添加可执行权限，否则执行会报错没有权限：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod 755 hello_shell.sh</span><br></pre></td></tr></table></figure>

<p>执行脚本：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">./hello_shell.sh</span><br></pre></td></tr></table></figure>

<p>创建一个 C 语言 <code>hello world</code> 程序：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">gedit hello_world.c</span><br></pre></td></tr></table></figure>

<p>输入如下内容，同样不能省略第一行。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">#include &lt;stdio.h&gt;</span><br><span class="line"></span><br><span class="line">int main(void)</span><br><span class="line">&#123;</span><br><span class="line">    printf(&quot;hello world!\n&quot;);</span><br><span class="line">    return 0;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>保存后使用 gcc 生成可执行文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">gcc -o hello_world hello_world.c</span><br></pre></td></tr></table></figure>

<p><strong>gcc 生成二进制文件默认具有可执行权限，不需要修改。</strong></p>
<p>在 <code>/home/shiyanlou</code> 家目录创建一个 <code>mybin</code> 目录，并将上述 <code>hello_shell.sh</code> 和 <code>hello_world</code> 文件移动到其中：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">mkdir mybin</span><br><span class="line">mv hello_shell.sh hello_world mybin/</span><br></pre></td></tr></table></figure>

<p>现在你可以在 <code>mybin</code> 目录中分别运行你刚刚创建的两个程序：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd mybin</span><br><span class="line">./hello_shell.sh</span><br><span class="line">./hello_world</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339433567.png" alt="此处输入图片的描述"></p>
<p>回到上一级目录，也就是 <code>shiyanlou</code> 家目录，当再想运行那两个程序时，会发现提示命令找不到，除非加上命令的完整路径，但那样很不方便，如何做到像使用系统命令一样执行自己创建的脚本文件或者程序呢？那就要将命令所在路径添加到 <code>PATH</code> 环境变量了。</p>
<h3 id="添加自定义路径到“-PATH-”环境变量"><a href="#添加自定义路径到“-PATH-”环境变量" class="headerlink" title="添加自定义路径到“ PATH ”环境变量"></a>添加自定义路径到“ PATH ”环境变量</h3><p>在前面我们应该注意到 <code>PATH</code> 里面的路径是以 <code>:</code> 作为分割符的，所以我们可以这样添加自定义路径：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">PATH=$PATH:/home/shiyanlou/mybin</span><br></pre></td></tr></table></figure>

<p><strong>注意这里一定要使用绝对路径。</strong></p>
<p>现在你就可以在任意目录执行那两个命令了（注意需要去掉前面的 <code>./</code>）。你可能会意识到这样还并没有很好的解决问题，因为我给 PATH 环境变量追加了一个路径，它也只是在当前 Shell 有效，我一旦退出终端，再打开就会发现又失效了。有没有方法让添加的环境变量全局有效？或者每次启动 Shell 时自动执行上面添加自定义路径到 PATH 的命令？下面我们就来说说后一种方式——让它自动执行。</p>
<p>在每个用户的 home 目录中有一个 Shell 每次启动时会默认执行一个配置脚本，以初始化环境，包括添加一些用户自定义环境变量等等。实验楼的环境使用的 Shell 是 zsh，它的配置文件是 <code>.zshrc</code>，相应的如果使用的 Shell 是 Bash，则配置文件为 <code>.bashrc</code>。它们在 <code>etc</code> 下还都有一个或多个全局的配置文件，不过我们一般只修改用户目录下的配置文件。Shell 的种类有很多，可以使用 <code>cat /etc/shells</code> 命令查看当前系统已安装的 Shell。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583223324878" alt="图片描述"></p>
<p>我们可以简单地使用下面命令直接添加内容到 <code>.zshrc</code> 中：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;PATH=$PATH:/home/shiyanlou/mybin&quot; &gt;&gt; .zshrc</span><br></pre></td></tr></table></figure>

<p><strong>上述命令中 &gt;&gt; 表示将标准输出以追加的方式重定向到一个文件中，注意前面用到的 &gt; 是以覆盖的方式重定向到一个文件中，使用的时候一定要注意分辨。在指定文件不存在的情况下都会创建新的文件。</strong></p>
<h3 id="修改和删除已有变量"><a href="#修改和删除已有变量" class="headerlink" title="修改和删除已有变量"></a>修改和删除已有变量</h3><h4 id="变量修改"><a href="#变量修改" class="headerlink" title="变量修改"></a>变量修改</h4><p>变量的修改有以下几种方式：</p>
<table>
<thead>
<tr>
<th>变量设置方式</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>$&#123;变量名#匹配字串&#125;</code></td>
<td>从头向后开始匹配，删除符合匹配字串的最短数据</td>
</tr>
<tr>
<td><code>$&#123;变量名##匹配字串&#125;</code></td>
<td>从头向后开始匹配，删除符合匹配字串的最长数据</td>
</tr>
<tr>
<td><code>$&#123;变量名%匹配字串&#125;</code></td>
<td>从尾向前开始匹配，删除符合匹配字串的最短数据</td>
</tr>
<tr>
<td><code>$&#123;变量名%%匹配字串&#125;</code></td>
<td>从尾向前开始匹配，删除符合匹配字串的最长数据</td>
</tr>
<tr>
<td><code>$&#123;变量名/旧的字串/新的字串&#125;</code></td>
<td>将符合旧字串的第一个字串替换为新的字串</td>
</tr>
<tr>
<td><code>$&#123;变量名//旧的字串/新的字串&#125;</code></td>
<td>将符合旧字串的全部字串替换为新的字串</td>
</tr>
</tbody></table>
<p>比如我们可以修改前面添加到 PATH 的环境变量，将添加的 mybin 目录从环境变量里删除。为了避免操作失误导致命令找不到，我们先将 PATH 赋值给一个新的自定义变量 mypath：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">mypath=$PATH</span><br><span class="line">echo $mypath</span><br><span class="line">mypath=$&#123;mypath%/home/shiyanlou/mybin&#125;</span><br><span class="line"># 或使用通配符 * 表示任意多个任意字符</span><br><span class="line">mypath=$&#123;mypath%*/mybin&#125;</span><br></pre></td></tr></table></figure>

<p>可以看到路径已经不存在了。</p>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583224278229" alt="图片描述"></p>
<h4 id="变量删除"><a href="#变量删除" class="headerlink" title="变量删除"></a>变量删除</h4><p>可以使用 <code>unset</code> 命令删除一个环境变量：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unset mypath</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583224422523" alt="图片描述"></p>
<h3 id="如何让环境变量立即生效"><a href="#如何让环境变量立即生效" class="headerlink" title="如何让环境变量立即生效"></a>如何让环境变量立即生效</h3><p>前面我们在 Shell 中修改了一个配置脚本文件之后（比如 zsh 的配置文件 home 目录下的 <code>.zshrc</code>），每次都要退出终端重新打开甚至重启主机之后其才能生效，很是麻烦，我们可以使用 <code>source</code> 命令来让其立即生效，如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">source .zshrc</span><br></pre></td></tr></table></figure>

<p><code>source</code> 命令还有一个别名就是 <code>.</code>，上面的命令如果替换成 <code>.</code> 的方式就该是：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">. ./.zshrc</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583225164807" alt="图片描述"></p>
<p>在使用 <code>.</code> 的时候，需要注意与表示当前路径的那个点区分开。</p>
<p>注意第一个点后面有一个空格，而且后面的文件必须指定完整的绝对或相对路径名，<code>source</code> 则不需要。</p>
<h2 id="搜索文件"><a href="#搜索文件" class="headerlink" title="搜索文件"></a>搜索文件</h2><p>与搜索相关的命令常用的有 <code>whereis</code>，<code>which</code>，<code>find</code> 和 <code>locate</code>。</p>
<ul>
<li><code>whereis</code> 简单快速</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">whereis who</span><br><span class="line">whereis find</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid60timestamp1532339453618.png" alt="此处输入图片的描述"></p>
<p>你会看到 <code>whereis find</code> 找到了三个路径，两个可执行文件路径和一个 man 在线帮助文件所在路径，这个搜索很快，因为它并没有从硬盘中依次查找，而是直接从数据库中查询。</p>
<p><code>whereis</code> 只能搜索二进制文件（<code>-b</code>），man 帮助文件（<code>-m</code>）和源代码文件（<code>-s</code>）。如果想要获得更全面的搜索结果可以使用 <code>locate</code> 命令。</p>
<ul>
<li><code>locate</code> 快而全</li>
</ul>
<p>使用 <code>locate</code> 命令查找文件也不会遍历硬盘，它通过查询 <code>/var/lib/mlocate/mlocate.db</code> 数据库来检索信息。不过这个数据库也不是实时更新的，系统会使用定时任务每天自动执行 <code>updatedb</code> 命令来更新数据库。所以有时候你刚添加的文件，它可能会找不到，需要手动执行一次 <code>updatedb</code> 命令（在我们的环境中必须先执行一次该命令）。注意这个命令也不是内置的命令，在部分环境中需要手动安装，然后执行更新。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install locate</span><br><span class="line">sudo updatedb</span><br></pre></td></tr></table></figure>

<p>它可以用来查找指定目录下的不同文件类型，如查找 <code>/etc</code> 下所有以 sh 开头的文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">locate /etc/sh</span><br></pre></td></tr></table></figure>

<blockquote>
<p><strong>注意，它不只是在 &#x2F;etc 目录下查找，还会自动递归子目录进行查找。</strong></p>
</blockquote>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583225846911" alt="图片描述"></p>
<p>查找 <code>/usr/share/</code> 下所有 jpg 文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">locate /usr/share/*.jpg</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20210113-1610502774649" alt="图片描述"></p>
<blockquote>
<p>环境里使用 zsh，在 <code>~/.zshrc</code> 文件里添加了 <code>setopt nonomatch</code> 配置，这样就不会自动处理和修复命令，因此可以不使用 <code>\</code> 转义。如果其他环境中执行该命令提示 <code>zsh: no matches found: /usr/share/*.jpg</code>，则可以在 <code>.zshrc</code> 中添加上述配置，或者使用 <code>\</code> 转义。</p>
</blockquote>
<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226161762" alt="图片描述"></p>
<p>如果想只统计数目可以加上 <code>-c</code> 参数，<code>-i</code> 参数可以忽略大小写进行查找，<code>whereis</code> 的 <code>-b</code>、<code>-m</code>、<code>-s</code> 同样可以使用。</p>
<ul>
<li><code>which</code> 小而精</li>
</ul>
<p><code>which</code> 本身是 Shell 内建的一个命令，我们通常使用 <code>which</code> 来确定是否安装了某个指定的程序，因为它只从 <code>PATH</code> 环境变量指定的路径中去搜索命令并且返回第一个搜索到的结果。也就是说，我们可以看到某个系统命令是否存在以及执行的到底是哪一个地方的命令。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">which man</span><br><span class="line">which nginx</span><br><span class="line">which ping</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226577160" alt="图片描述"></p>
<ul>
<li><code>find</code> 精而细</li>
</ul>
<p><code>find</code> 应该是这几个命令中最强大的了，它不但可以通过文件类型、文件名进行查找而且可以根据文件的属性（如文件的时间戳，文件的权限等）进行搜索。<code>find</code> 命令强大到，要把它讲明白至少需要单独好几节课程才行，我们这里只介绍一些常用的内容。</p>
<p>这条命令表示去 <code>/etc/</code> 目录下面 ，搜索名字叫做 interfaces 的文件或者目录。这是 <code>find</code> 命令最常见的格式，千万记住 <code>find</code> 的第一个参数是要搜索的地方。命令前面加上 <code>sudo</code> 是因为 shiyanlou 只是普通用户，对 <code>/etc</code> 目录下的很多文件都没有访问的权限，如果是 root 用户则不用使用。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo find /etc/ -name interfaces</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226847941" alt="图片描述"></p>
<blockquote>
<p><strong>注意 find 命令的路径是作为第一个参数的， 基本命令格式为 find [path][option] [action] 。</strong></p>
</blockquote>
<p>与时间相关的命令参数：</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-atime</code></td>
<td>最后访问时间</td>
</tr>
<tr>
<td><code>-ctime</code></td>
<td>最后修改文件内容的时间</td>
</tr>
<tr>
<td><code>-mtime</code></td>
<td>最后修改文件属性的时间</td>
</tr>
</tbody></table>
<p>下面以 <code>-mtime</code> 参数举例：</p>
<ul>
<li><code>-mtime n</code>：n 为数字，表示为在 n 天之前的“一天之内”修改过的文件</li>
<li><code>-mtime +n</code>：列出在 n 天之前（不包含 n 天本身）被修改过的文件</li>
<li><code>-mtime -n</code>：列出在 n 天之内（包含 n 天本身）被修改过的文件</li>
<li><code>-newer file</code>：file 为一个已存在的文件，列出比 file 还要新的文件名</li>
</ul>
<p><img src="https://doc.shiyanlou.com/linux_base/5-8.png" alt="1"></p>
<p>列出 home 目录中，当天（24 小时之内）有改动的文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find ~ -mtime 0</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583226953512" alt="图片描述"></p>
<p>列出用户家目录下比 &#x2F;etc 目录新的文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find ~ -newer /etc</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200303-1583227074890" alt="图片描述"></p>
<h1 id="文件打包及解压缩"><a href="#文件打包及解压缩" class="headerlink" title="文件打包及解压缩"></a>文件打包及解压缩</h1><h2 id="基本概念"><a href="#基本概念" class="headerlink" title="基本概念"></a>基本概念</h2><p>在讲 Linux 上的压缩工具之前，有必要先了解一下常见常用的压缩包文件格式。在 Windows 上最常见的不外乎这两种 <code>*.zip</code>，<code>*.7z</code> 后缀的压缩文件。而在 Linux 上面常见的格式除了以上两种外，还有 <code>.rar</code>，<code>*.gz</code>，<code>*.xz</code>，<code>*.bz2</code>，<code>*.tar</code>，<code>*.tar.gz</code>，<code>*.tar.xz</code>，<code>*.tar.bz2</code>，简单介绍如下：</p>
<table>
<thead>
<tr>
<th>文件后缀名</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>*.zip</code></td>
<td>zip 程序打包压缩的文件</td>
</tr>
<tr>
<td><code>*.rar</code></td>
<td>rar 程序压缩的文件</td>
</tr>
<tr>
<td><code>*.7z</code></td>
<td>7zip 程序压缩的文件</td>
</tr>
<tr>
<td><code>*.tar</code></td>
<td>tar 程序打包，未压缩的文件</td>
</tr>
<tr>
<td><code>*.gz</code></td>
<td>gzip 程序（GNU zip）压缩的文件</td>
</tr>
<tr>
<td><code>*.xz</code></td>
<td>xz 程序压缩的文件</td>
</tr>
<tr>
<td><code>*.bz2</code></td>
<td>bzip2 程序压缩的文件</td>
</tr>
<tr>
<td><code>*.tar.gz</code></td>
<td>tar 打包，gzip 程序压缩的文件</td>
</tr>
<tr>
<td><code>*.tar.xz</code></td>
<td>tar 打包，xz 程序压缩的文件</td>
</tr>
<tr>
<td><code>*tar.bz2</code></td>
<td>tar 打包，bzip2 程序压缩的文件</td>
</tr>
<tr>
<td><code>*.tar.7z</code></td>
<td>tar 打包，7z 程序压缩的文件</td>
</tr>
</tbody></table>
<p>讲了这么多种压缩文件，这么多个命令，不过我们一般只需要掌握几个命令即可，包括 <code>zip</code>，<code>tar</code>。下面会依次介绍这几个命令及对应的解压命令。</p>
<h2 id="打包与解压缩"><a href="#打包与解压缩" class="headerlink" title="打包与解压缩"></a>打包与解压缩</h2><h3 id="zip-压缩打包程序"><a href="#zip-压缩打包程序" class="headerlink" title="zip 压缩打包程序"></a>zip 压缩打包程序</h3><ul>
<li>使用 zip 打包文件夹，注意输入完整的参数和路径：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">zip -r -q -o shiyanlou.zip /home/shiyanlou/Desktop</span><br><span class="line">du -h shiyanlou.zip</span><br><span class="line">file shiyanlou.zip</span><br></pre></td></tr></table></figure>

<p>上面命令将目录 <code>/home/shiyanlou/Desktop</code> 打包成一个文件，并查看了打包后文件的大小和类型。第一行命令中，<code>-r</code> 参数表示递归打包包含子目录的全部内容，<code>-q</code> 参数表示为安静模式，即不向屏幕输出信息，<code>-o</code>，表示输出文件，需在其后紧跟打包输出文件名。后面使用 <code>du</code> 命令查看打包后文件的大小（后面会具体说明该命令）。</p>
<ul>
<li>设置压缩级别为 9 和 1（9 最大，1 最小），重新打包：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">zip -r -9 -q -o shiyanlou_9.zip /home/shiyanlou/Desktop -x ~/*.zip</span><br><span class="line">zip -r -1 -q -o shiyanlou_1.zip /home/shiyanlou/Desktop -x ~/*.zip</span><br></pre></td></tr></table></figure>

<p>这里添加了一个参数用于设置压缩级别 <code>-[1-9]</code>，1 表示最快压缩但体积大，9 表示体积最小但耗时最久。最后那个 <code>-x</code> 是为了排除我们上一次创建的 zip 文件，否则又会被打包进这一次的压缩文件中，<strong>注意：这里只能使用绝对路径，否则不起作用</strong>。</p>
<p>我们再用 <code>du</code> 命令分别查看默认压缩级别、最低、最高压缩级别及未压缩的文件的大小：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">du -h -d 0 *.zip ~ | sort</span><br></pre></td></tr></table></figure>

<p>通过 man 手册可知：</p>
<ul>
<li><code>-h</code>， –human-readable（顾名思义，你可以试试不加的情况）</li>
<li><code>-d</code>， –max-depth（所查看文件的深度）</li>
</ul>
<p><img src="https://doc.shiyanlou.com/courses/uid600404-20190428-1556438181236" alt="图片描述"></p>
<p>这样一目了然，理论上来说默认压缩级别应该是最高的，但是由于文件不大，这里的差异不明显（几乎看不出差别），不过你在环境中操作之后看到的压缩文件大小可能跟图上的有些不同，因为系统在使用过程中，会随时生成一些缓存文件在当前用户的家目录中，这对于我们学习命令使用来说，是无关紧要的，可以忽略这些不同。</p>
<ul>
<li>创建加密 zip 包</li>
</ul>
<p>使用 <code>-e</code> 参数可以创建加密压缩包：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zip -r -e -o shiyanlou_encryption.zip /home/shiyanlou/Desktop</span><br></pre></td></tr></table></figure>

<p><strong>注意：</strong> 关于 <code>zip</code> 命令，因为 Windows 系统与 Linux&#x2F;Unix 在文本文件格式上的一些兼容问题，比如换行符（为不可见字符），在 Windows 为 CR+LF（Carriage-Return+Line-Feed：回车加换行），而在 Linux&#x2F;Unix 上为 LF（换行），所以如果在不加处理的情况下，在 Linux 上编辑的文本，在 Windows 系统上打开可能看起来是没有换行的。如果你想让你在 Linux 创建的 zip 压缩文件在 Windows 上解压后没有任何问题，那么你还需要对命令做一些修改：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">zip -r -l -o shiyanlou.zip /home/shiyanlou/Desktop</span><br></pre></td></tr></table></figure>

<p>需要加上 <code>-l</code> 参数将 <code>LF</code> 转换为 <code>CR+LF</code> 来达到以上目的。</p>
<h3 id="使用-unzip-命令解压缩-zip-文件"><a href="#使用-unzip-命令解压缩-zip-文件" class="headerlink" title="使用 unzip 命令解压缩 zip 文件"></a>使用 unzip 命令解压缩 zip 文件</h3><p>将 <code>shiyanlou.zip</code> 解压到当前目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unzip shiyanlou.zip</span><br></pre></td></tr></table></figure>

<p>使用安静模式，将文件解压到指定目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unzip -q shiyanlou.zip -d ziptest</span><br></pre></td></tr></table></figure>

<p>上述指定目录不存在，将会自动创建。如果你不想解压只想查看压缩包的内容你可以使用 <code>-l</code> 参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unzip -l shiyanlou.zip</span><br></pre></td></tr></table></figure>

<p><strong>注意：</strong> 使用 unzip 解压文件时我们同样应该注意兼容问题，不过这里我们关心的不再是上面的问题，而是中文编码的问题，通常 Windows 系统上面创建的压缩文件，如果有有包含中文的文档或以中文作为文件名的文件时默认会采用 GBK 或其它编码，而 Linux 上面默认使用的是 UTF-8 编码，如果不加任何处理，直接解压的话可能会出现中文乱码的问题（有时候它会自动帮你处理），为了解决这个问题，我们可以在解压时指定编码类型。</p>
<p>使用 <code>-O</code>（英文字母，大写 o）参数指定编码类型：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">unzip -O GBK 中文压缩文件.zip</span><br></pre></td></tr></table></figure>

<h3 id="tar-打包工具"><a href="#tar-打包工具" class="headerlink" title="tar 打包工具"></a>tar 打包工具</h3><p>在 Linux 上面更常用的是 <code>tar</code> 工具，tar 原本只是一个打包工具，只是同时还是实现了对 7z、gzip、xz、bzip2 等工具的支持，这些压缩工具本身只能实现对文件或目录（单独压缩目录中的文件）的压缩，没有实现对文件的打包压缩，所以我们也无需再单独去学习其他几个工具，tar 的解压和压缩都是同一个命令，只需参数不同，使用比较方便。</p>
<p>下面先掌握 <code>tar</code> 命令一些基本的使用方式，即不进行压缩只是进行打包（创建归档文件）和解包的操作。</p>
<ul>
<li>创建一个 tar 包：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line">tar -P -cf shiyanlou.tar /home/shiyanlou/Desktop</span><br></pre></td></tr></table></figure>

<p>上面命令中，<code>-P</code> 保留绝对路径符，<code>-c</code> 表示创建一个 tar 包文件，<code>-f</code> 用于指定创建的文件名，注意文件名必须紧跟在 <code>-f</code> 参数之后，比如不能写成 <code>tar -fc shiyanlou.tar</code>，可以写成 <code>tar -f shiyanlou.tar -c ~</code>。你还可以加上 <code>-v</code> 参数以可视的的方式输出打包的文件。</p>
<ul>
<li>解包一个文件（<code>-x</code> 参数）到指定路径的<strong>已存在</strong>目录（<code>-C</code> 参数）：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mkdir tardir</span><br><span class="line">tar -xf shiyanlou.tar -C tardir</span><br></pre></td></tr></table></figure>

<ul>
<li>只查看不解包文件 <code>-t</code> 参数：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -tf shiyanlou.tar</span><br></pre></td></tr></table></figure>

<ul>
<li>保留文件属性和跟随链接（符号链接或软链接），有时候我们使用 tar 备份文件当你在其他主机还原时希望保留文件的属性（<code>-p</code> 参数）和备份链接指向的源文件而不是链接本身（<code>-h</code> 参数）：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -cphf etc.tar /etc</span><br></pre></td></tr></table></figure>

<p>对于创建不同的压缩格式的文件，对于 tar 来说是相当简单的，需要的只是换一个参数，这里我们就以使用 <code>gzip</code> 工具创建 <code>*.tar.gz</code> 文件为例来说明。</p>
<ul>
<li>我们只需要在创建 tar 文件的基础上添加 <code>-z</code> 参数，使用 <code>gzip</code> 来压缩文件：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -czf shiyanlou.tar.gz /home/shiyanlou/Desktop</span><br></pre></td></tr></table></figure>

<ul>
<li>解压 <code>*.tar.gz</code> 文件：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xzf shiyanlou.tar.gz</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid61timestamp1532339561961.png" alt="此处输入图片的描述"></p>
<p>现在我们要使用其它的压缩工具创建或解压相应文件只需要更改一个参数即可：</p>
<table>
<thead>
<tr>
<th>压缩文件格式</th>
<th>参数</th>
</tr>
</thead>
<tbody><tr>
<td><code>*.tar.gz</code></td>
<td><code>-z</code></td>
</tr>
<tr>
<td><code>*.tar.xz</code></td>
<td><code>-J</code></td>
</tr>
<tr>
<td><code>*tar.bz2</code></td>
<td><code>-j</code></td>
</tr>
</tbody></table>
<blockquote>
<p>tar 命令的参数很多，不过常用的就是上述这些，需要了解更多你可以查看 man 手册获取帮助。</p>
</blockquote>
<h1 id="文件系统操作与磁盘管理"><a href="#文件系统操作与磁盘管理" class="headerlink" title="文件系统操作与磁盘管理"></a>文件系统操作与磁盘管理</h1><h2 id="基本操作"><a href="#基本操作" class="headerlink" title="基本操作"></a>基本操作</h2><h4 id="查看磁盘和目录的容量"><a href="#查看磁盘和目录的容量" class="headerlink" title="查看磁盘和目录的容量"></a>查看磁盘和目录的容量</h4><ul>
<li>使用 <code>df</code> 命令查看磁盘的容量</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">df</span><br></pre></td></tr></table></figure>

<p>在实验楼的环境中你将看到如下的输出内容：</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523871472488.png" alt="此处输入图片的描述"></p>
<p>但在实际的物理主机上会更像这样：</p>
<p><img src="https://doc.shiyanlou.com/linux_base/7-2.png" alt="1"></p>
<p>物理主机上的 <code>/dev/sda2</code> 是对应着主机硬盘的分区，后面的数字表示分区号，数字前面的字母 a 表示第几块硬盘（也可能是可移动磁盘），你如果主机上有多块硬盘则可能还会出现 <code>/dev/sdb</code>，<code>/dev/sdc</code> 这些磁盘设备都会在 <code>/dev</code> 目录下以文件的存在形式。</p>
<p>接着你还会看到”1k-块”这个陌生的东西，它表示以磁盘块大小的方式显示容量，后面为相应的以块大小表示的已用和可用容量，在你了解 Linux 的文件系统之前这个就先不管吧，我们以一种你应该看得懂的方式展示：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">df -h</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523871955863.png" alt="此处输入图片的描述"></p>
<p>现在你就可以使用命令查看你主机磁盘的使用情况了。至于挂载点如果你还记得前面第 4 节介绍 Linux 目录树结构的内容，那么你就应该能很好的理解挂载的概念，这里就不再赘述。</p>
<ul>
<li>使用 <code>du</code> 命令查看目录的容量</li>
</ul>
<p>这个命令前面其实已经用了很多次了：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 默认同样以块的大小展示</span><br><span class="line">du</span><br><span class="line"># 加上 `-h` 参数，以更易读的方式展示</span><br><span class="line">du -h</span><br></pre></td></tr></table></figure>

<p><code>-d</code> 参数指定查看目录的深度</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 只查看 1 级目录的信息</span><br><span class="line">du -h -d 0 ~</span><br><span class="line"># 查看 2 级</span><br><span class="line">du -h -d 1 ~</span><br></pre></td></tr></table></figure>

<p>常用参数</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">du -h # 同 --human-readable 以 K，M，G 为单位，提高信息的可读性。</span><br><span class="line">du -a # 同 --all 显示目录中所有文件的大小。</span><br><span class="line">du -s # 同 --summarize 仅显示总计，只列出最后加总的值。</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523872284604.png" alt="此处输入图片的描述"></p>
<p><code>du</code>（estimate file space usage）命令与 <code>df</code>（report file system disk space usage）命令只有一字之差，希望大家注意不要弄混淆了，你可以像我这样从 man 手册中获取命令的完整描述，记全称就不会搞混了。</p>
<h2 id="简单的磁盘管理"><a href="#简单的磁盘管理" class="headerlink" title="简单的磁盘管理"></a>简单的磁盘管理</h2><h3 id="创建虚拟磁盘"><a href="#创建虚拟磁盘" class="headerlink" title="创建虚拟磁盘"></a>创建虚拟磁盘</h3><h4 id="dd-命令简介"><a href="#dd-命令简介" class="headerlink" title="dd 命令简介"></a>dd 命令简介</h4><p><code>dd</code> 命令用于转换和复制文件，不过它的复制不同于 <code>cp</code>。之前提到过关于 Linux 的很重要的一点，<strong>一切即文件</strong>，在 Linux 上，硬件的设备驱动（如硬盘）和特殊设备文件（如 <code>/dev/zero</code> 和 <code>/dev/random</code>）都像普通文件一样，只是在各自的驱动程序中实现了对应的功能，<code>dd</code> 也可以读取文件或写入这些文件。这样，<code>dd</code> 也可以用在备份硬件的引导扇区、获取一定数量的随机数据或者空数据等任务中。<code>dd</code> 程序也可以在复制时处理数据，例如转换字节序、或在 ASCII 与 EBCDIC 编码间互换。</p>
<p><code>dd</code> 的命令行语句与其他的 Linux 程序不同，因为它的命令行选项格式为 <strong>选项&#x3D;值</strong>，而不是更标准的 <strong>–选项 值</strong> 或 <strong>-选项&#x3D;值</strong>。<code>dd</code> 默认从标准输入中读取，并写入到标准输出中，但可以用选项 <code>if</code>（input file，输入文件）和 <code>of</code>（output file，输出文件）改变。</p>
<p>我们先来试试用 <code>dd</code> 命令从标准输入读入用户的输入到标准输出或者一个文件中：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 输出到文件</span><br><span class="line">dd of=test bs=10 count=1 # 或者 dd if=/dev/stdin of=test bs=10 count=1</span><br><span class="line"># 输出到标准输出</span><br><span class="line">dd if=/dev/stdin of=/dev/stdout bs=10 count=1</span><br><span class="line"># 在打完了这个命令后，继续在终端打字，作为你的输入</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339776332.png" alt="此处输入图片的描述"></p>
<p>上述命令从标准输入设备读入用户输入（缺省值，所以可省略）然后输出到 test 文件，<code>bs</code>（block size）用于指定块大小（缺省单位为 Byte，也可为其指定如 <code>K</code>，<code>M</code>，<code>G</code> 等单位），<code>count</code> 用于指定块数量。如上图所示，我指定只读取总共 10 个字节的数据，当我输入了 <code>hello shiyanlou</code> 之后加上空格回车总共 16 个字节（一个英文字符占一个字节）内容，显然超过了设定大小。使用 <code>du</code> 和 <code>cat</code> 10 个字节（那个黑底百分号表示这里没有换行符），而其他的多余输入将被截取并保留在标准输入。</p>
<p>前面说到 <code>dd</code> 在拷贝的同时还可以实现数据转换，那下面就举一个简单的例子：将输出的英文字符转换为大写再写入文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dd if=/dev/stdin of=test bs=10 count=1 conv=ucase</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339755321.png" alt="此处输入图片的描述"></p>
<p>你可以在<code>man</code>文档中查看其他所有转换参数。</p>
<h4 id="使用-dd-命令创建虚拟镜像文件"><a href="#使用-dd-命令创建虚拟镜像文件" class="headerlink" title="使用 dd 命令创建虚拟镜像文件"></a>使用 dd 命令创建虚拟镜像文件</h4><p>通过上面一小节，你应该掌握了 <code>dd</code> 的基本使用，下面就来使用 <code>dd</code> 命令来完成创建虚拟磁盘的第一步。</p>
<p>从 <code>/dev/zero</code> 设备创建一个容量为 256M 的空文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">dd if=/dev/zero of=virtual.img bs=1M count=256</span><br><span class="line">du -h virtual.img</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339693208.png" alt="此处输入图片的描述"></p>
<p>然后我们要将这个文件格式化（写入文件系统），这里我们要学到一个（准确的说是一组）新的命令来完成这个需求。</p>
<h4 id="使用-mkfs-命令格式化磁盘（我们这里是自己创建的虚拟磁盘镜像）"><a href="#使用-mkfs-命令格式化磁盘（我们这里是自己创建的虚拟磁盘镜像）" class="headerlink" title="使用 mkfs 命令格式化磁盘（我们这里是自己创建的虚拟磁盘镜像）"></a>使用 mkfs 命令格式化磁盘（我们这里是自己创建的虚拟磁盘镜像）</h4><p>你可以在命令行输入 <code>sudo mkfs</code> 然后按下 <code>&lt;Tab&gt;</code> 键，你可以看到很多个以 mkfs 为前缀的命令，这些不同的后缀其实就是表示着不同的文件系统，可以用 mkfs 格式化成的文件系统。</p>
<p>我们可以简单的使用下面的命令来将我们的虚拟磁盘镜像格式化为 <code>ext4</code> 文件系统：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo mkfs.ext4 virtual.img</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523873459128.png" alt="此处输入图片的描述"></p>
<p>可以看到实际 <code>mkfs.ext4</code> 是使用 <code>mke2fs</code> 来完成格式化工作的。<code>mke2fs</code> 的参数很多，不过我们也不会经常格式化磁盘来玩，所以就掌握这基本用法吧，等你有特殊需求时，再查看 man 文档解决。</p>
<p>更多关于文件系统的知识，请查看 wiki： <a target="_blank" rel="noopener" href="http://zh.wikipedia.org/wiki/%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F#Linux_.E6.94.AF.E6.8F.B4.E7.9A.84.E6.AA.94.E6.A1.88.E7.B3.BB.E7.B5.B1">文件系统</a> <a target="_blank" rel="noopener" href="http://zh.wikipedia.org/wiki/Ext3">ext3</a>，<a target="_blank" rel="noopener" href="http://zh.wikipedia.org/wiki/Ext4">ext4</a></p>
<p>如果你想知道 Linux 支持哪些文件系统你可以输入 <code>ls -l /lib/modules/$(uname -r)/kernel/fs</code> 查看（我们的环境中无法查看）。</p>
<h4 id="使用-mount-命令挂载磁盘到目录树"><a href="#使用-mount-命令挂载磁盘到目录树" class="headerlink" title="使用 mount 命令挂载磁盘到目录树"></a>使用 mount 命令挂载磁盘到目录树</h4><p>用户在 Linux&#x2F;UNIX 的机器上打开一个文件以前，包含该文件的文件系统必须先进行挂载的动作，此时用户要对该文件系统执行 <code>mount</code> 的指令以进行挂载。该指令通常是使用在 USB 或其他可移除存储设备上，而根目录则需要始终保持挂载的状态。又因为 Linux&#x2F;UNIX 文件系统可以对应一个文件而不一定要是硬件设备，所以可以挂载一个包含文件系统的文件到目录树。</p>
<p>Linux&#x2F;UNIX 命令行的 <code>mount</code> 指令是告诉操作系统，对应的文件系统已经准备好，可以使用了，而该文件系统会对应到一个特定的点（称为挂载点）。挂载好的文件、目录、设备以及特殊文件即可提供用户使用。</p>
<p>我们先来使用 <code>mount</code> 来查看下主机已经挂载的文件系统：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo mount</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523874300781.png" alt="此处输入图片的描述"></p>
<p>输出的结果中每一行表示一个设备或虚拟设备，每一行最前面是设备名，然后是 on 后面是挂载点，type 后面表示文件系统类型，再后面是挂载选项（比如可以在挂载时设定以只读方式挂载等等）。</p>
<p>那么我们如何挂载真正的磁盘到目录树呢，<code>mount</code> 命令的一般格式如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mount [options] [source] [directory]</span><br></pre></td></tr></table></figure>

<p>一些常用操作：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mount [-o [操作选项]] [-t 文件系统类型] [-w|--rw|--ro] [文件系统源] [挂载点]</span><br></pre></td></tr></table></figure>

<p><strong>注意：由于实验楼的环境限制，mount 命令挂载及 umount 卸载都无法进行操作，可以简单了解这些步骤。</strong></p>
<p>现在直接来挂载我们创建的虚拟磁盘镜像到 <code>/mnt</code> 目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mount -o loop -t ext4 virtual.img /mnt</span><br><span class="line"># 也可以省略挂载类型，很多时候 mount 会自动识别</span><br><span class="line"></span><br><span class="line"># 以只读方式挂载</span><br><span class="line">mount -o loop --ro virtual.img /mnt</span><br><span class="line"># 或者 mount -o loop,ro virtual.img /mnt</span><br></pre></td></tr></table></figure>

<h4 id="使用-umount-命令卸载已挂载磁盘"><a href="#使用-umount-命令卸载已挂载磁盘" class="headerlink" title="使用 umount 命令卸载已挂载磁盘"></a>使用 umount 命令卸载已挂载磁盘</h4><p><strong>注意：由于实验楼的环境限制，mount 命令挂载及 umount 卸载都无法进行操作，可以简单了解这些步骤。</strong></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 命令格式 sudo umount 已挂载设备名或者挂载点，如：</span><br><span class="line">sudo umount /mnt</span><br></pre></td></tr></table></figure>

<p>不过遗憾的是，由于我们环境的问题（环境中使用的 Linux 内核在编译时没有添加对 Loop device 的支持），所以你将无法挂载成功：</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6122timestamp1523925358180.png" alt="此处输入图片的描述"></p>
<p>另外关于 loop 设备，你可能会有诸多疑问，那么请看下面来自维基百科 <a target="_blank" rel="noopener" href="http://zh.wikipedia.org/wiki//dev/loop">&#x2F;dev&#x2F;loop</a>的说明：</p>
<blockquote>
<p>在类 UNIX 系统中，&#x2F;dev&#x2F;loop（或称 vnd （vnode disk）、lofi（循环文件接口））是一种伪设备，这种设备使得文件可以如同块设备一般被访问。</p>
<p>在使用之前，循环设备必须与现存文件系统上的文件相关联。这种关联将提供给用户一个应用程序接口，接口将允许文件视为块特殊文件（参见设备文件系统）使用。因此，如果文件中包含一个完整的文件系统，那么这个文件就能如同磁盘设备一般被挂载。</p>
<p>这种设备文件经常被用于光盘或是磁盘镜像。通过循环挂载来挂载包含文件系统的文件，便使处在这个文件系统中的文件得以被访问。这些文件将出现在挂载点目录。如果挂载目录中本身有文件，这些文件在挂载后将被禁止使用。</p>
</blockquote>
<h4 id="使用-fdisk-为磁盘分区"><a href="#使用-fdisk-为磁盘分区" class="headerlink" title="使用 fdisk 为磁盘分区"></a>使用 fdisk 为磁盘分区</h4><p>（关于分区的一些概念不清楚的用户请参看 <a target="_blank" rel="noopener" href="http://zh.wikipedia.org/wiki/%E4%B8%BB%E5%BC%95%E5%AF%BC%E8%AE%B0%E5%BD%95">主引导记录</a>）</p>
<p><strong>注意：由于实验楼的环境限制，fdisk 命令无法进行操作，可以简单了解这些步骤。</strong></p>
<p>同样因为环境中没有物理磁盘，也无法创建虚拟磁盘的原因我们就无法实验练习使用该命令了，下面我将以我的物理主机为例讲解如何为磁盘分区。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 查看硬盘分区表信息</span><br><span class="line">sudo fdisk -l</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/linux_base/7-12.png" alt="1"></p>
<p>输出结果中开头显示了我主机上的磁盘的一些信息，包括容量扇区数，扇区大小，I&#x2F;O 大小等信息。</p>
<p>我们重点看一下中间的分区信息，<code>/dev/sda1</code>，<code>/dev/sda2</code> 为主分区分别安装了 Windows 和 Linux 操作系统，<code>/dev/sda3</code> 为交换分区（可以理解为虚拟内存），<code>/dev/sda4</code> 为扩展分区其中包含 <code>/dev/sda5</code>，<code>/dev/sda6</code>，<code>/dev/sda7</code>，<code>/dev/sda8</code> 四个逻辑分区，因为主机上有几个分区之间有空隙，没有对齐边界扇区，所以分区之间不是完全连续的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 进入磁盘分区模式</span><br><span class="line">sudo fdisk virtual.img</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/linux_base/7-13.png" alt="1"></p>
<p>在进行操作前我们首先应先规划好我们的分区方案，这里我将在使用 128M（可用 127M 左右）的虚拟磁盘镜像创建一个 30M 的主分区剩余部分为扩展分区包含 2 个大约 45M 的逻辑分区。</p>
<p>操作完成后输入 <code>p</code> 查看结果如下:</p>
<p><img src="https://doc.shiyanlou.com/linux_base/7-14.png" alt="1"></p>
<p>最后不要忘记输入 <code>w</code> 写入分区表。</p>
<h4 id="使用-losetup-命令建立镜像与回环设备的关联"><a href="#使用-losetup-命令建立镜像与回环设备的关联" class="headerlink" title="使用 losetup 命令建立镜像与回环设备的关联"></a>使用 losetup 命令建立镜像与回环设备的关联</h4><p><strong>注意：由于实验楼的环境限制，losetup 命令无法进行操作，可以简单了解这些步骤。</strong></p>
<p>同样因为环境原因中没有物理磁盘，也没有 loop device 的原因我们就无法实验练习使用该命令了，下面我将以我的物理主机为例讲解。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo losetup /dev/loop0 virtual.img</span><br><span class="line"># 如果提示设备忙你也可以使用其它的回环设备，&quot;ls /dev/loop*&quot;参看所有回环设备</span><br><span class="line"></span><br><span class="line"># 解除设备关联</span><br><span class="line">sudo losetup -d /dev/loop0</span><br></pre></td></tr></table></figure>

<p>然后再使用 <code>mkfs</code> 格式化各分区（前面我们是格式化整个虚拟磁盘镜像文件或磁盘），不过格式化之前，我们还要为各分区建立虚拟设备的映射，用到 <code>kpartx</code> 工具，需要先安装：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install kpartx</span><br><span class="line">sudo kpartx -av /dev/loop0</span><br><span class="line"></span><br><span class="line"># 取消映射</span><br><span class="line">sudo kpartx -dv /dev/loop0</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/linux_base/7-15.png" alt="pic"></p>
<p>接着再是格式化，我们将其全部格式化为 ext4：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo mkfs.ext4 -q /dev/mapper/loop0p1</span><br><span class="line">sudo mkfs.ext4 -q /dev/mapper/loop0p5</span><br><span class="line">sudo mkfs.ext4 -q /dev/mapper/loop0p6</span><br></pre></td></tr></table></figure>

<p>格式化完成后在 <code>/media</code> 目录下新建四个空目录用于挂载虚拟磁盘：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /media/virtualdisk_&#123;1..3&#125;</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"># 挂载磁盘分区</span><br><span class="line">sudo mount /dev/mapper/loop0p1 /media/virtualdisk_1</span><br><span class="line">sudo mount /dev/mapper/loop0p5 /media/virtualdisk_2</span><br><span class="line">sudo mount /dev/mapper/loop0p6 /media/virtualdisk_3</span><br><span class="line"></span><br><span class="line"># 卸载磁盘分区</span><br><span class="line">sudo umount /dev/mapper/loop0p1</span><br><span class="line">sudo umount /dev/mapper/loop0p5</span><br><span class="line">sudo umount /dev/mapper/loop0p6</span><br></pre></td></tr></table></figure>

<p>然后：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">df -h</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/linux_base/7-16.png" alt="pic"></p>
<h4 id="轻松一下"><a href="#轻松一下" class="headerlink" title="轻松一下"></a>轻松一下</h4><p><code>cowsay</code> 命令，可以让你在终端里以一种动物说话的形式打印出一段话。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"># 更新软件包</span><br><span class="line">sudo apt update</span><br><span class="line"></span><br><span class="line"># 安装</span><br><span class="line">sudo apt install -y cowsay</span><br><span class="line"></span><br><span class="line"># 默认是一只牛</span><br><span class="line">cowsay hello shiyanlou</span><br><span class="line"></span><br><span class="line"># 加上&#x27;-l&#x27;参数打印所有支持的动物（其实不只是动物）种类</span><br><span class="line">cowsay -l</span><br><span class="line"></span><br><span class="line"># 使用&#x27;-f&#x27;参数选择动物种类</span><br><span class="line">cowsay -f elephant hello shiyanlou</span><br><span class="line"></span><br><span class="line"># 安装 fortune-zh</span><br><span class="line">sudo apt-get install fortune-zh</span><br><span class="line"></span><br><span class="line"># 此外它还可以结合我们之前的作业讲过的 fortune 命令一起使用</span><br><span class="line">/usr/games/fortune | cowsay -f daemon</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid62timestamp1532339794389.png" alt="此处输入图片的描述"></p>
<h1 id="Linux-下的帮助命令"><a href="#Linux-下的帮助命令" class="headerlink" title="Linux 下的帮助命令"></a>Linux 下的帮助命令</h1><h2 id="内建命令与外部命令"><a href="#内建命令与外部命令" class="headerlink" title="内建命令与外部命令"></a>内建命令与外部命令</h2><p>什么是内建命令，什么是外部命令呢？这和帮助命令又有什么关系呢？</p>
<p>因为有一些查看帮助的工具在内建命令与外建命令上是有区别对待的。</p>
<blockquote>
<p><strong>内建命令</strong>实际上是 shell 程序的一部分，其中包含的是一些比较简单的 Linux 系统命令，这些命令是写在 bash 源码的 builtins 里面的，由 shell 程序识别并在 shell 程序内部完成运行，通常在 Linux 系统加载运行时 shell 就被加载并驻留在系统内存中。而且解析内部命令 shell 不需要创建子进程，因此其执行速度比外部命令快。比如：history、cd、exit 等等。</p>
</blockquote>
<blockquote>
<p><strong>外部命令</strong>是 Linux 系统中的实用程序部分，因为实用程序的功能通常都比较强大，所以其包含的程序量也会很大，在系统加载时并不随系统一起被加载到内存中，而是在需要时才将其调入内存。虽然其不包含在 shell 中，但是其命令执行过程是由 shell 程序控制的。外部命令是在 Bash 之外额外安装的，通常放在&#x2F;bin，&#x2F;usr&#x2F;bin，&#x2F;sbin，&#x2F;usr&#x2F;sbin 等等。比如：ls、vi 等。</p>
</blockquote>
<p>简单来说就是：一个是天生自带的天赋技能，一个是后天得来的附加技能。我们可以使用 type 命令来区分命令是内建的还是外部的。例如这两个得出的结果是不同的</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">type exit</span><br><span class="line"></span><br><span class="line">type vim</span><br></pre></td></tr></table></figure>

<p>得到的是两种结果，若是对 ls 你还能得到第三种结果</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6123timestamp1523930371175.png" alt="此处输入图片的描述"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 得到这样的结果说明是内建命令，正如上文所说内建命令都是在 bash 源码中的 builtins 的.def中</span><br><span class="line">xxx is a shell builtin</span><br><span class="line"># 得到这样的结果说明是外部命令，正如上文所说，外部命令在/usr/bin or /usr/sbin等等中</span><br><span class="line">xxx is /usr/bin/xxx</span><br><span class="line"># 若是得到alias的结果，说明该指令为命令别名所设定的名称；</span><br><span class="line">xxx is an alias for xx --xxx</span><br></pre></td></tr></table></figure>

<h2 id="帮助命令的使用"><a href="#帮助命令的使用" class="headerlink" title="帮助命令的使用"></a>帮助命令的使用</h2><h3 id="help-命令"><a href="#help-命令" class="headerlink" title="help 命令"></a>help 命令</h3><p> 本实验环境是 zsh，而 zsh 中内置并没有 help 命令，我们可以进入 bash 中，在 bash 中内置有该命令</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bash</span><br></pre></td></tr></table></figure>

<p>做好了以上的准备，我们就可以愉快的使用 help 命令了，我们可以尝试下这个命令:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">help ls</span><br></pre></td></tr></table></figure>

<p>得到的结果如图所示，为什么是这样的结果？</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6123timestamp1523930924973.png" alt="此处输入图片的描述"></p>
<p>因为 help 命令是用于显示 shell 内建命令的简要帮助信息。帮助信息中显示有该命令的简要说明以及一些参数的使用以及说明，一定记住 help 命令只能用于显示内建命令的帮助信息，不然就会得到你刚刚得到的结果。</p>
<p>那如果是外部命令怎么办，不能就这么抛弃它呀。其实外部命令基本上都有一个参数 <code>--help</code>，这样就可以得到相应的帮助，看到你想要的东西了。试试下面这个命令是不是能看到你想要的东西了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls --help</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6123timestamp1523931303648.png" alt="此处输入图片的描述"></p>
<h3 id="man-命令"><a href="#man-命令" class="headerlink" title="man 命令"></a>man 命令</h3><p>你可以尝试下这个命令</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">man ls</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081467871829217" alt="实验楼"></p>
<p>得到的内容比用 help 更多更详细，而且 man 没有内建与外部命令的区分，因为 man 工具是显示系统手册页中的内容，也就是一本电子版的字典，这些内容大多数都是对命令的解释信息，还有一些相关的描述。通过查看系统文档中的 man 也可以得到程序的更多相关信息和 Linux 的更多特性。</p>
<p>是不是好用许多，当然也不代表 help 就没有存在的必要，当你非常紧急只是忘记该用哪个参数的时候，help 这种显示简单扼要的信息就特别实用，若是不太紧急的时候就可以用 man 这种详细描述的查询方式</p>
<p>在尝试上面这个命令时我们会发现最左上角显示“ LS （1）”，在这里，“ LS ”表示手册名称，而“（1）”表示该手册位于第一章节。这个章节又是什么？在 man 手册中一共有这么几个章节</p>
<table>
<thead>
<tr>
<th>章节数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>1</code></td>
<td>Standard commands （标准命令）</td>
</tr>
<tr>
<td><code>2</code></td>
<td>System calls （系统调用）</td>
</tr>
<tr>
<td><code>3</code></td>
<td>Library functions （库函数）</td>
</tr>
<tr>
<td><code>4</code></td>
<td>Special devices （设备说明）</td>
</tr>
<tr>
<td><code>5</code></td>
<td>File formats （文件格式）</td>
</tr>
<tr>
<td><code>6</code></td>
<td>Games and toys （游戏和娱乐）</td>
</tr>
<tr>
<td><code>7</code></td>
<td>Miscellaneous （杂项）</td>
</tr>
<tr>
<td><code>8</code></td>
<td>Administrative Commands （管理员命令）</td>
</tr>
<tr>
<td><code>9</code></td>
<td>其他（Linux 特定的）， 用来存放内核例行程序的文档。</td>
</tr>
</tbody></table>
<p>打开手册之后我们可以通过 pgup 与 pgdn 或者上下键来上下翻看，可以按 q 退出当前页面</p>
<h3 id="info-命令"><a href="#info-命令" class="headerlink" title="info 命令"></a>info 命令</h3><p>要是你觉得 man 显示的信息都还不够，满足不了你的需求，那试试 info 命令，注意实验楼的环境中没有安装 info，可以手动安装，安装和操作步骤如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 安装 info</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install info</span><br><span class="line"># 查看 ls 命令的 info</span><br><span class="line">info ls</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468210358613" alt="Info_for_ls"></p>
<p>得到的信息是不是比 man 还要多了，info 来自自由软件基金会的 GNU 项目，是 GNU 的超文本帮助系统，能够更完整的显示出 GNU 信息。所以得到的信息当然更多</p>
<p>man 和 info 就像两个集合，它们有一个交集部分，但与 man 相比，info 工具可显示更完整的 GNU 工具信息。若 man 页包含的某个工具的概要信息在 info 中也有介绍，那么 man 页中会有“请参考 info 页更详细内容”的字样。</p>
<h1 id="Linux-任务计划-crontab"><a href="#Linux-任务计划-crontab" class="headerlink" title="Linux 任务计划 crontab"></a>Linux 任务计划 crontab</h1><h2 id="crontab-的使用"><a href="#crontab-的使用" class="headerlink" title="crontab 的使用"></a>crontab 的使用</h2><p>crontab 命令常见于 Unix 和类 Unix 的操作系统之中（Linux 就属于类 Unix 操作系统），用于设置周期性被执行的指令。 </p>
<h3 id="crontab-简介"><a href="#crontab-简介" class="headerlink" title="crontab 简介"></a>crontab 简介</h3><p>crontab 命令从输入设备读取指令，并将其存放于 crontab 文件中，以供之后读取和执行。通常，crontab 储存的指令被守护进程激活，crond 为其守护进程，crond 常常在后台运行，每一分钟会检查一次是否有预定的作业需要执行。</p>
<p>通过 crontab 命令，我们可以在固定的间隔时间执行指定的系统指令或 shell 脚本。时间间隔的单位可以是分钟、小时、日、月、周的任意组合。</p>
<p>这里我们看一看 crontab 的格式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># Example of job definition:</span><br><span class="line"># .---------------- minute (0 - 59)</span><br><span class="line"># |  .------------- hour (0 - 23)</span><br><span class="line"># |  |  .---------- day of month (1 - 31)</span><br><span class="line"># |  |  |  .------- month (1 - 12) OR jan,feb,mar,apr ...</span><br><span class="line"># |  |  |  |  .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat</span><br><span class="line"># |  |  |  |  |</span><br><span class="line"># *  *  *  *  * user-name command to be executed</span><br></pre></td></tr></table></figure>

<h3 id="crontab-准备"><a href="#crontab-准备" class="headerlink" title="crontab 准备"></a>crontab 准备</h3><p>crontab 在本实验环境中需要做一些特殊的准备，首先我们会启动 <code>rsyslog</code>，以便我们可以通过日志中的信息来了解我们的任务是否真正的被执行了（在本实验环境中需要手动启动，而在自己本地中 Ubuntu 会默认自行启动不需要手动启动）。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y rsyslog</span><br><span class="line">sudo service rsyslog start</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468201394787" alt="service-rsyslog-start"></p>
<p>在本实验环境中 crontab 也是不被默认启动的，同时不能在后台由 upstart 来管理，所以需要我们来启动它:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cron －f &amp;</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523941816405.png" alt="此处输入图片的描述"></p>
<h3 id="crontab-使用"><a href="#crontab-使用" class="headerlink" title="crontab 使用"></a>crontab 使用</h3><p>下面将开始 crontab 的使用了，我们通过下面一个命令来添加一个计划任务：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">crontab -e</span><br></pre></td></tr></table></figure>

<p>第一次启动会出现这样一个画面，这是让我们选择编辑的工具，选择第二个基本的 vim 就可以了。</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523941985569.png" alt="此处输入图片的描述"></p>
<p>而选择后我们会进入这样一个画面，这就是添加计划的地方了，与一般的配置文档相同，以#号开头的都是注释，通过文档的最后一排我们可以猜猜 crontab 的格式是什么样的呢？</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468202029108" alt="实验楼"></p>
<p>详细的格式可以使用上一节中学习到的 man 命令查看：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">man crontab</span><br></pre></td></tr></table></figure>

<p>在了解命令格式之后，我们通过这样的一个例子来完成一个任务的添加，在文档的最后一排加上这样一排命令，该任务是每分钟我们会在&#x2F;home&#x2F;shiyanlou 目录下创建一个以当前的年月日时分秒为名字的空白文件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">*/1 * * * * touch /home/shiyanlou/$(date +\%Y\%m\%d\%H\%M\%S)</span><br></pre></td></tr></table></figure>

<p><strong>注意：</strong></p>
<blockquote>
<p>“ % ” 在 crontab 文件中，有结束命令行、换行、重定向的作用，前面加 ” \ ” 符号转义，否则，“ % ” 符号将执行其结束命令行或者换行的作用，并且其后的内容会被做为标准输入发送给前面的命令。</p>
</blockquote>
<p>添加成功后我们会得到最后一排 installing new crontab 的一个提示：</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468203483143" alt="实验楼"></p>
<p>当然我们也可以通过这样的一个指令来查看我们添加了哪些任务：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">crontab -l</span><br></pre></td></tr></table></figure>

<p>通过图中的显示，我们也可以看出，我们正确的保存并且添加成功了该任务的：</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468204230683" alt="实验楼"></p>
<p>虽然我们添加了任务，但是如果 <code>cron</code> 的守护进程并没有启动，它根本都不会监测到有任务，当然也就不会帮我们执行，我们可以通过以下 2 种方式来确定我们的 <code>cron</code> 是否成功的在后台启动，默默的帮我们做事，若是没有就得执行上文准备中的第二步了。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">ps aux | grep cron</span><br><span class="line"></span><br><span class="line"># or</span><br><span class="line"></span><br><span class="line">pgrep cron</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523942683532.png" alt="此处输入图片的描述"></p>
<p>通过下图可以看到任务在创建之后，执行了几次，生成了一些文件，且每分钟生成一个：</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523943532369.png" alt="此处输入图片的描述"></p>
<p>我们通过这样一个命令可以查看到执行任务命令之后在日志中的信息反馈：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo tail -f /var/log/syslog</span><br></pre></td></tr></table></figure>

<p>从图中我们可以看到分别在 13 点 28、29、30 分的 01 秒为我们在 shiyanlou 用户的家目录下创建了文件。</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523943327065.png" alt="此处输入图片的描述"></p>
<p>当我们并不需要这个任务的时候我们可以使用这么一个命令去删除任务：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">crontab -r</span><br></pre></td></tr></table></figure>

<p>通过图中我们可以看出我们删除之后再查看任务列表，系统已经显示该用户并没有任务哦。</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6124timestamp1523943647348.png" alt="此处输入图片的描述"></p>
<h2 id="crontab-的深入"><a href="#crontab-的深入" class="headerlink" title="crontab 的深入"></a>crontab 的深入</h2><p>每个用户使用 <code>crontab -e</code> 添加计划任务，都会在 <code>/var/spool/cron/crontabs</code> 中添加一个该用户自己的任务文档，这样目的是为了隔离。</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468206283987" alt="实验楼"></p>
<p>如果是系统级别的定时任务，需要 root 权限执行的任务应该怎么处理？</p>
<p>只需要使用 <code>sudo</code> 编辑 <code>/etc/crontab</code> 文件就可以。</p>
<p><code>cron</code> 服务监测时间最小单位是分钟，所以 <code>cron</code> 会每分钟去读取一次 <code>/etc/crontab</code> 与 <code>/var/spool/cron/crontabs</code> 里面的內容。</p>
<p>在 <code>/etc</code> 目录下，<code>cron</code> 相关的目录有下面几个：</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468206856712" alt="实验楼"></p>
<p>每个目录的作用：</p>
<ol>
<li><code>/etc/cron.daily</code>，目录下的脚本会每天执行一次，在每天的 6 点 25 分时运行；</li>
<li><code>/etc/cron.hourly</code>，目录下的脚本会每个小时执行一次，在每小时的 17 分钟时运行；</li>
<li><code>/etc/cron.monthly</code>，目录下的脚本会每月执行一次，在每月 1 号的 6 点 52 分时运行；</li>
<li><code>/etc/cron.weekly</code>，目录下的脚本会每周执行一次，在每周第七天的 6 点 47 分时运行；</li>
</ol>
<p>系统默认执行时间可以根据需求进行修改。</p>
<h1 id="命令执行顺序控制与管道"><a href="#命令执行顺序控制与管道" class="headerlink" title="命令执行顺序控制与管道"></a>命令执行顺序控制与管道</h1><h2 id="命令执行顺序的控制"><a href="#命令执行顺序的控制" class="headerlink" title="命令执行顺序的控制"></a>命令执行顺序的控制</h2><p>通常情况下，我们每次只能在终端输入一条命令，按下回车执行，执行完成后，我们再输入第二条命令，然后再按回车执行。当有时候我们会一次输入多条命令，这个时候的执行过程又是如何的呢？下面我们将为大家详细讲解下命令的执行顺序的控制问题。 </p>
<h3 id="顺序执行多条命令"><a href="#顺序执行多条命令" class="headerlink" title="顺序执行多条命令"></a>顺序执行多条命令</h3><p>当我们需要使用 <code>apt-get</code> 安装一个软件，然后安装完成后立即运行安装的软件或命令工具，又恰巧你的主机才更换的软件源还没有更新软件列表（比如之前我们的环境中，每次重新开始实验就得 <code>sudo apt-get update</code>，否则可能会报错提示 404），那么你可能会有如下一系列操作：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line"># 等待执行完毕，然后输入下面的命令</span><br><span class="line">sudo apt-get install some-tool # 这里 some-tool 需要替换成具体的软件包</span><br><span class="line"># 等待安装完毕，然后输入软件包名称执行</span><br><span class="line">some-tool</span><br></pre></td></tr></table></figure>

<p>例如，目前环境下没有安装过支持 rar 压缩包管理器，可以使用命令如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install rar</span><br><span class="line"></span><br><span class="line">rar</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/1/1700764/dc52d96ef7ca2bcde69ceab88f15537d-0" alt="图片描述"></p>
<p>指定软件包安装后：</p>
<p><img src="https://doc.shiyanlou.com/courses/1/1700764/8f72e47862086647925ea14ef01442ae-0" alt="图片描述"></p>
<p>这时你可能就会想：要是我可以一次性输入完，让它自己去依次执行各命令就好了，这就是我们这一小节要解决的问题。</p>
<p>简单的顺序执行你可以使用 <code>;</code> 来完成，比如上述操作你可以：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update;sudo apt-get install some-tool;some-tool # 让它自己运行</span><br></pre></td></tr></table></figure>

<h3 id="有选择的执行命令"><a href="#有选择的执行命令" class="headerlink" title="有选择的执行命令"></a>有选择的执行命令</h3><p>关于上面的操作，不知你有没有思考过一个问题，如果我们在让它自动顺序执行命令时，前面的命令执行不成功，而后面的命令又依赖于上一条命令的结果，那么就会造成花了时间，最终却得到一个错误的结果，而且有时候直观的看你还无法判断结果是否正确。那么我们需要能够有选择性的来执行命令，比如上一条命令执行成功才继续下一条，或者不成功又该做出其它什么处理，比如我们使用 <code>which</code> 来查找是否安装某个命令，如果找到就执行该命令，否则什么也不做，虽然这个操作没有什么实际意义，但可帮你更好的理解一些概念：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">which cowsay&gt;/dev/null &amp;&amp; cowsay -f head-in ohch~</span><br></pre></td></tr></table></figure>

<p>你如果没有安装 <code>cowsay</code>，你可以先执行一次上述命令，你会发现什么也没发生，你再安装好之后你再执行一次上述命令，你也会发现一些惊喜。</p>
<p>上面的 <code>&amp;&amp;</code> 就是用来实现选择性执行的，它表示如果前面的命令执行结果（不是表示终端输出的内容，而是表示命令执行状态的结果）返回 0 则执行后面的，否则不执行，你可以从 <code>$?</code> 环境变量获取上一次命令的返回结果：</p>
<p><img src="https://doc.shiyanlou.com/document-uid1labid63timestamp1544148440172.png" alt="此处输入图片的描述"></p>
<p>学习过 C 语言的用户应该知道在 C 语言里面 <code>&amp;&amp;</code> 表示逻辑与，而且还有一个 <code>||</code> 表示逻辑或，同样 Shell 也有一个 <code>||</code>，它们的区别就在于，shell 中的这两个符号除了也可用于表示逻辑与和或之外，就是可以实现这里的命令执行顺序的简单控制。<code>||</code> 在这里就是与 <code>&amp;&amp;</code> 相反的控制效果，当上一条命令执行结果为 <code>≠0(\$?≠0)</code> 时则执行它后面的命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">which cowsay&gt;/dev/null || echo &quot;cowsay has not been install, please run &#x27;sudo apt-get install cowsay&#x27; to install&quot;</span><br></pre></td></tr></table></figure>

<p>除了上述基本的使用之外，我们还可以结合着 <code>&amp;&amp;</code> 和 <code>||</code> 来实现一些操作，比如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">which cowsay&gt;/dev/null &amp;&amp; echo &quot;exist&quot; || echo &quot;not exist&quot;</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414664955.png" alt="此处输入图片的描述"></p>
<p>我画个流程图来解释一下上面的流程：</p>
<p><img src="https://doc.shiyanlou.com/linux_base/8-3.png" alt="1"></p>
<h2 id="管道"><a href="#管道" class="headerlink" title="管道"></a>管道</h2><p>管道是一种通信机制，通常用于进程间的通信（也可通过 socket 进行网络通信），它表现出来的形式就是将前面每一个进程的输出（stdout）直接作为下一个进程的输入（stdin）。</p>
<p>管道又分为匿名管道和具名管道（这里将不会讨论在源程序中使用系统调用创建并使用管道的情况，它与命令行的管道在内核中实际都是采用相同的机制）。我们在使用一些过滤程序时经常会用到的就是匿名管道，在命令行中由 <code>|</code> 分隔符表示，<code>|</code> 在前面的内容中我们已经多次使用到了。具名管道简单的说就是有名字的管道，通常只会在源程序中用到具名管道。下面我们就将通过一些常用的可以使用管道的过滤程序来帮助你熟练管道的使用。</p>
<h3 id="试用"><a href="#试用" class="headerlink" title="试用"></a>试用</h3><p>先试用一下管道，比如查看 <code>/etc</code> 目录下有哪些文件和目录，使用 <code>ls</code> 命令来查看：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -al /etc</span><br></pre></td></tr></table></figure>

<p>有太多内容，屏幕不能完全显示，这时候可以使用滚动条或快捷键滚动窗口来查看。不过这时候可以使用管道：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -al /etc | less</span><br></pre></td></tr></table></figure>

<p>通过管道将前一个命令(<code>ls</code>)的输出作为下一个命令(<code>less</code>)的输入，然后就可以一行一行地看。</p>
<h3 id="cut-命令，打印每一行的某一字段"><a href="#cut-命令，打印每一行的某一字段" class="headerlink" title="cut 命令，打印每一行的某一字段"></a>cut 命令，打印每一行的某一字段</h3><p>打印 <code>/etc/passwd</code> 文件中以 <code>:</code> 为分隔符的第 1 个字段和第 6 个字段分别表示用户名和其家目录：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cut /etc/passwd -d &#x27;:&#x27; -f 1,6</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414685006.png" alt="此处输入图片的描述"></p>
<p>打印 <code>/etc/passwd</code> 文件中每一行的前 N 个字符：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 前五个（包含第五个）</span><br><span class="line">cut /etc/passwd -c -5</span><br><span class="line"># 前五个之后的（包含第五个）</span><br><span class="line">cut /etc/passwd -c 5-</span><br><span class="line"># 第五个</span><br><span class="line">cut /etc/passwd -c 5</span><br><span class="line"># 2 到 5 之间的（包含第五个）</span><br><span class="line">cut /etc/passwd -c 2-5</span><br></pre></td></tr></table></figure>

<h3 id="grep-命令，在文本中或-stdin-中查找匹配字符串"><a href="#grep-命令，在文本中或-stdin-中查找匹配字符串" class="headerlink" title="grep 命令，在文本中或 stdin 中查找匹配字符串"></a>grep 命令，在文本中或 stdin 中查找匹配字符串</h3><p><code>grep</code> 命令是很强大的，也是相当常用的一个命令，它结合正则表达式可以实现很复杂却很高效的匹配和查找，不过在学习正则表达式之前，这里介绍它简单的使用，而关于正则表达式后面将会有单独一小节介绍到时会再继续学习 <code>grep</code> 命令和其他一些命令。</p>
<p><code>grep</code> 命令的一般形式为：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grep [命令选项]... 用于匹配的表达式 [文件]...</span><br></pre></td></tr></table></figure>

<p>还是先体验一下，我们搜索<code>/home/shiyanlou</code>目录下所有包含”shiyanlou”的文本文件，并显示出现在文本中的行号：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">grep -rnI &quot;shiyanlou&quot; ~</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414709836.png" alt="此处输入图片的描述"></p>
<p><code>-r</code> 参数表示递归搜索子目录中的文件，<code>-n</code> 表示打印匹配项行号，<code>-I</code> 表示忽略二进制文件。这个操作实际没有多大意义，但可以感受到 <code>grep</code> 命令的强大与实用。</p>
<p>当然也可以在匹配字段中使用正则表达式，下面简单的演示：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 查看环境变量中以 &quot;yanlou&quot; 结尾的字符串</span><br><span class="line">export | grep &quot;.*yanlou$&quot;</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414725827.png" alt="此处输入图片的描述"></p>
<p>其中<code>$</code>就表示一行的末尾。</p>
<h3 id="wc-命令，简单小巧的计数工具"><a href="#wc-命令，简单小巧的计数工具" class="headerlink" title="wc 命令，简单小巧的计数工具"></a>wc 命令，简单小巧的计数工具</h3><p>wc 命令用于统计并输出一个文件中行、单词和字节的数目，比如输出 <code>/etc/passwd</code> 文件的统计信息：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wc /etc/passwd</span><br></pre></td></tr></table></figure>

<p>分别只输出行数、单词数、字节数、字符数和输入文本中最长一行的字节数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"># 行数</span><br><span class="line">wc -l /etc/passwd</span><br><span class="line"># 单词数</span><br><span class="line">wc -w /etc/passwd</span><br><span class="line"># 字节数</span><br><span class="line">wc -c /etc/passwd</span><br><span class="line"># 字符数</span><br><span class="line">wc -m /etc/passwd</span><br><span class="line"># 最长行字节数</span><br><span class="line">wc -L /etc/passwd</span><br></pre></td></tr></table></figure>

<p><strong>注意：对于西文字符来说，一个字符就是一个字节，但对于中文字符一个汉字是大于 2 个字节的，具体数目是由字符编码决定的。</strong></p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414808838.png" alt="此处输入图片的描述"></p>
<p>再来结合管道来操作一下，下面统计 &#x2F;etc 下面所有目录数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls -dl /etc/*/ | wc -l</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6125timestamp1523946094712.png" alt="此处输入图片的描述"></p>
<h3 id="sort-排序命令"><a href="#sort-排序命令" class="headerlink" title="sort 排序命令"></a>sort 排序命令</h3><p>这个命令前面我们也是用过多次，功能很简单就是将输入按照一定方式排序，然后再输出，它支持的排序有按字典排序，数字排序，按月份排序，随机排序，反转排序，指定特定字段进行排序等等。</p>
<p>默认为字典排序：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/passwd | sort</span><br></pre></td></tr></table></figure>

<p>反转排序：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/passwd | sort -r</span><br></pre></td></tr></table></figure>

<p>按特定字段排序：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/passwd | sort -t&#x27;:&#x27; -k 3</span><br></pre></td></tr></table></figure>

<p>上面的<code>-t</code>参数用于指定字段的分隔符，这里是以”:”作为分隔符；<code>-k 字段号</code>用于指定对哪一个字段进行排序。这里<code>/etc/passwd</code>文件的第三个字段为数字，默认情况下是以字典序排序的，如果要按照数字排序就要加上<code>-n</code>参数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/passwd | sort -t&#x27;:&#x27; -k 3 -n</span><br></pre></td></tr></table></figure>

<p>注意观察第二个冒号后的数字： <img src="https://doc.shiyanlou.com/document-uid735639labid63timestamp1532414849333.png" alt="此处输入图片的描述"></p>
<h3 id="uniq-去重命令"><a href="#uniq-去重命令" class="headerlink" title="uniq 去重命令"></a>uniq 去重命令</h3><p><code>uniq</code> 命令可以用于过滤或者输出重复行。</p>
<ul>
<li>过滤重复行</li>
</ul>
<p>我们可以使用 <code>history</code> 命令查看最近执行过的命令（实际为读取 <code>$&#123;SHELL&#125;_history</code> 文件，如我们环境中的 <code>.zsh_history</code> 文件），不过你可能只想查看使用了哪个命令而不需要知道具体干了什么，那么你可能就会要想去掉命令后面的参数然后去掉重复的命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">history | cut -c 8- | cut -d &#x27; &#x27; -f 1 | uniq</span><br></pre></td></tr></table></figure>

<p>然后经过层层过滤，你会发现确是只输出了执行的命令那一列，不过去重效果好像不明显，仔细看你会发现它确实去重了，只是不那么明显，之所以不明显是因为 <code>uniq</code> 命令只能去连续重复的行，不是全文去重，所以要达到预期效果，我们先排序：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">history | cut -c 8- | cut -d &#x27; &#x27; -f 1 | sort | uniq</span><br><span class="line"># 或者</span><br><span class="line">history | cut -c 8- | cut -d &#x27; &#x27; -f 1 | sort -u</span><br></pre></td></tr></table></figure>

<p>这就是 Linux&#x2F;UNIX 哲学吸引人的地方，大繁至简，一个命令只干一件事却能干到最好。</p>
<ul>
<li>输出重复行</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 输出重复过的行（重复的只输出一个）及重复次数</span><br><span class="line">history | cut -c 8- | cut -d &#x27; &#x27; -f 1 | sort | uniq -dc</span><br><span class="line"># 输出所有重复的行</span><br><span class="line">history | cut -c 8- | cut -d &#x27; &#x27; -f 1 | sort | uniq -D</span><br></pre></td></tr></table></figure>

<p>文本处理命令还有很多，下一节将继续介绍一些常用的文本处理的命令。</p>
<h1 id="简单的文本处理"><a href="#简单的文本处理" class="headerlink" title="简单的文本处理"></a>简单的文本处理</h1><h2 id="文本处理命令"><a href="#文本处理命令" class="headerlink" title="文本处理命令"></a>文本处理命令</h2><h3 id="tr-命令"><a href="#tr-命令" class="headerlink" title="tr 命令"></a>tr 命令</h3><p>tr 命令可以用来删除一段文本信息中的某些文字。或者将其进行转换。</p>
<h4 id="使用方式"><a href="#使用方式" class="headerlink" title="使用方式"></a>使用方式</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tr [option]...SET1 [SET2]</span><br></pre></td></tr></table></figure>

<h4 id="常用的选项有"><a href="#常用的选项有" class="headerlink" title="常用的选项有"></a>常用的选项有</h4><table>
<thead>
<tr>
<th>选项</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-d</code></td>
<td>删除和 set1 匹配的字符，注意不是全词匹配也不是按字符顺序匹配</td>
</tr>
<tr>
<td><code>-s</code></td>
<td>去除 set1 指定的在输入文本中连续并重复的字符</td>
</tr>
</tbody></table>
<h4 id="操作举例"><a href="#操作举例" class="headerlink" title="操作举例"></a>操作举例</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 删除 &quot;hello shiyanlou&quot; 中所有的&#x27;o&#x27;，&#x27;l&#x27;，&#x27;h&#x27;</span><br><span class="line">$ echo &#x27;hello shiyanlou&#x27; | tr -d &#x27;olh&#x27;</span><br><span class="line"># 将&quot;hello&quot; 中的ll，去重为一个l</span><br><span class="line">$ echo &#x27;hello&#x27; | tr -s &#x27;l&#x27;</span><br><span class="line"># 将输入文本，全部转换为大写或小写输出</span><br><span class="line">$ echo &#x27;input some text here&#x27; | tr &#x27;[:lower:]&#x27; &#x27;[:upper:]&#x27;</span><br><span class="line"># 上面的&#x27;[:lower:]&#x27; &#x27;[:upper:]&#x27;你也可以简单的写作&#x27;[a-z]&#x27; &#x27;[A-Z]&#x27;，当然反过来将大写变小写也是可以的</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414877239.png" alt="此处输入图片的描述"></p>
<p>更多 tr 的使用，你可以使用<code>--help</code>或者<code>man tr</code>获得。</p>
<h3 id="col-命令"><a href="#col-命令" class="headerlink" title="col 命令"></a>col 命令</h3><p>col 命令可以将<code>Tab</code>换成对等数量的空格键，或反转这个操作。</p>
<h4 id="使用方式-1"><a href="#使用方式-1" class="headerlink" title="使用方式"></a>使用方式</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">col [option]</span><br></pre></td></tr></table></figure>

<h4 id="常用的选项有-1"><a href="#常用的选项有-1" class="headerlink" title="常用的选项有"></a>常用的选项有</h4><table>
<thead>
<tr>
<th>选项</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-x</code></td>
<td>将<code>Tab</code>转换为空格</td>
</tr>
<tr>
<td><code>-h</code></td>
<td>将空格转换为<code>Tab</code>（默认选项）</td>
</tr>
</tbody></table>
<h4 id="操作举例-1"><a href="#操作举例-1" class="headerlink" title="操作举例"></a>操作举例</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 查看 /etc/protocols 中的不可见字符，可以看到很多 ^I ，这其实就是 Tab 转义成可见字符的符号</span><br><span class="line">cat -A /etc/protocols</span><br><span class="line"># 使用 col -x 将 /etc/protocols 中的 Tab 转换为空格，然后再使用 cat 查看，你发现 ^I 不见了</span><br><span class="line">cat /etc/protocols | col -x | cat -A</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414886554.png" alt="此处输入图片的描述"></p>
<h3 id="join-命令"><a href="#join-命令" class="headerlink" title="join 命令"></a>join 命令</h3><p>学过数据库的用户对这个应该不会陌生，这个命令就是用于将两个文件中包含相同内容的那一行合并在一起。</p>
<h4 id="使用方式-2"><a href="#使用方式-2" class="headerlink" title="使用方式"></a>使用方式</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">join [option]... file1 file2</span><br></pre></td></tr></table></figure>

<h4 id="常用的选项有-2"><a href="#常用的选项有-2" class="headerlink" title="常用的选项有"></a>常用的选项有</h4><table>
<thead>
<tr>
<th>选项</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-t</code></td>
<td>指定分隔符，默认为空格</td>
</tr>
<tr>
<td><code>-i</code></td>
<td>忽略大小写的差异</td>
</tr>
<tr>
<td><code>-1</code></td>
<td>指明第一个文件要用哪个字段来对比，默认对比第一个字段</td>
</tr>
<tr>
<td><code>-2</code></td>
<td>指明第二个文件要用哪个字段来对比，默认对比第一个字段</td>
</tr>
</tbody></table>
<h4 id="操作举例-2"><a href="#操作举例-2" class="headerlink" title="操作举例"></a>操作举例</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">cd /home/shiyanlou</span><br><span class="line"># 创建两个文件</span><br><span class="line">echo &#x27;1 hello&#x27; &gt; file1</span><br><span class="line">echo &#x27;1 shiyanlou&#x27; &gt; file2</span><br><span class="line">join file1 file2</span><br><span class="line"># 将 /etc/passwd 与 /etc/shadow 两个文件合并，指定以&#x27;:&#x27;作为分隔符</span><br><span class="line">sudo join -t&#x27;:&#x27; /etc/passwd /etc/shadow</span><br><span class="line"># 将 /etc/passwd 与 /etc/group 两个文件合并，指定以&#x27;:&#x27;作为分隔符，分别比对第4和第3个字段</span><br><span class="line">sudo join -t&#x27;:&#x27; -1 4 /etc/passwd -2 3 /etc/group</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414902443.png" alt="此处输入图片的描述"> <img src="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414948354.png" alt="此处输入图片的描述"></p>
<h3 id="paste-命令"><a href="#paste-命令" class="headerlink" title="paste 命令"></a>paste 命令</h3><p><code>paste</code>这个命令与<code>join</code> 命令类似，它是在不对比数据的情况下，简单地将多个文件合并一起，以<code>Tab</code>隔开。</p>
<h4 id="使用方式-3"><a href="#使用方式-3" class="headerlink" title="使用方式"></a>使用方式</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">paste [option] file...</span><br></pre></td></tr></table></figure>

<h4 id="常用的选项有-3"><a href="#常用的选项有-3" class="headerlink" title="常用的选项有"></a>常用的选项有</h4><table>
<thead>
<tr>
<th>选项</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-d</code></td>
<td>指定合并的分隔符，默认为 Tab</td>
</tr>
<tr>
<td><code>-s</code></td>
<td>不合并到一行，每个文件为一行</td>
</tr>
</tbody></table>
<h4 id="操作举例-3"><a href="#操作举例-3" class="headerlink" title="操作举例"></a>操作举例</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">echo hello &gt; file1</span><br><span class="line">echo shiyanlou &gt; file2</span><br><span class="line">echo www.shiyanlou.com &gt; file3</span><br><span class="line">paste -d &#x27;:&#x27; file1 file2 file3</span><br><span class="line">paste -s file1 file2 file3</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid337timestamp1532414967936.png" alt="此处输入图片的描述"></p>
<h1 id="数据流重定向"><a href="#数据流重定向" class="headerlink" title="数据流重定向"></a>数据流重定向</h1><h2 id="数据流重定向-1"><a href="#数据流重定向-1" class="headerlink" title="数据流重定向"></a>数据流重定向</h2><h3 id="简单的重定向"><a href="#简单的重定向" class="headerlink" title="简单的重定向"></a>简单的重定向</h3><p>在更多了解 Linux 的重定向之前，我们需要先知道一些基本的东西，前面我们已经提到过 Linux 默认提供了三个特殊设备，用于终端的显示和输出，分别为 <code>stdin</code>（标准输入，对应于你在终端的输入），<code>stdout</code>（标准输出，对应于终端的输出），<code>stderr</code>（标准错误输出，对应于终端的输出）。</p>
<table>
<thead>
<tr>
<th>文件描述符</th>
<th>设备文件</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>0</code></td>
<td><code>/dev/stdin</code></td>
<td>标准输入</td>
</tr>
<tr>
<td><code>1</code></td>
<td><code>/dev/stdout</code></td>
<td>标准输出</td>
</tr>
<tr>
<td><code>2</code></td>
<td><code>/dev/stderr</code></td>
<td>标准错误</td>
</tr>
</tbody></table>
<blockquote>
<p>文件描述符：文件描述符在形式上是一个非负整数。实际上，它是一个索引值，指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时，内核向进程返回一个文件描述符。在程序设计中，一些涉及底层的程序编写往往会围绕着文件描述符展开。但是文件描述符这一概念往往只适用于 UNIX、Linux 这样的操作系统。</p>
</blockquote>
<p>我们可以这样使用这些文件描述符。例如默认使用终端的标准输入作为命令的输入和标准输出作为命令的输出：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat # 按 Ctrl+C 退出</span><br></pre></td></tr></table></figure>

<p>将 cat 的连续输出（heredoc 方式）重定向到一个文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">mkdir Documents</span><br><span class="line">cat &gt; Documents/test.c &lt;&lt;EOF</span><br><span class="line">#include &lt;stdio.h&gt;</span><br><span class="line"></span><br><span class="line">int main()</span><br><span class="line">&#123;</span><br><span class="line">    printf(&quot;hello world\n&quot;);</span><br><span class="line">    return 0;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">EOF</span><br></pre></td></tr></table></figure>

<p>将一个文件作为命令的输入，标准输出作为命令的输出：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat Documents/test.c</span><br></pre></td></tr></table></figure>

<p>将 echo 命令通过管道传过来的数据作为 cat 命令的输入，将标准输出作为命令的输出：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &#x27;hi&#x27; | cat</span><br></pre></td></tr></table></figure>

<p>将 echo 命令的输出从默认的标准输出重定向到一个普通文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">echo &#x27;hello shiyanlou&#x27; &gt; redirect</span><br><span class="line">cat redirect</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid346timestamp1532415296335.png" alt="此处输入图片的描述"></p>
<p>初学者这里要注意不要将管道和重定向混淆，<strong>管道默认是连接前一个命令的输出到下一个命令的输入</strong>，而重定向通常是需要一个文件来建立两个命令的连接，你可以仔细体会一下上述第三个操作和最后两个操作的异同点。</p>
<h3 id="标准错误重定向"><a href="#标准错误重定向" class="headerlink" title="标准错误重定向"></a>标准错误重定向</h3><p> 重定向标准输出到文件，这是一个很实用的操作，另一个很实用的操作是将标准错误重定向，标准输出和标准错误都被指向伪终端的屏幕显示，所以我们经常看到的一个命令的输出通常是同时包含了标准输出和标准错误的结果的。比如下面的操作：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># 使用cat 命令同时读取两个文件，其中一个存在，另一个不存在</span><br><span class="line">cat Documents/test.c hello.c</span><br><span class="line"># 你可以看到除了正确输出了前一个文件的内容，还在末尾出现了一条错误信息</span><br><span class="line"># 下面我们将输出重定向到一个文件</span><br><span class="line">cat Documents/test.c hello.c &gt; somefile</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6127timestamp1523951670892.png" alt="此处输入图片的描述"></p>
<p>遗憾的是，这里依然出现了那条错误信息，这正是因为如我上面说的那样，标准输出和标准错误虽然都指向终端屏幕，实际它们并不一样。那有的时候我们就是要隐藏某些错误或者警告，那又该怎么做呢。这就需要用到我们前面讲的文件描述符了：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 将标准错误重定向到标准输出，再将标准输出重定向到文件，注意要将重定向到文件写到前面</span><br><span class="line">cat Documents/test.c hello.c &gt;somefile  2&gt;&amp;1</span><br><span class="line"># 或者只用bash提供的特殊的重定向符号&quot;&amp;&quot;将标准错误和标准输出同时重定向到文件</span><br><span class="line">cat Documents/test.c hello.c &amp;&gt;somefilehell</span><br></pre></td></tr></table></figure>

<p><strong>注意你应该在输出重定向文件描述符前加上&amp;，否则 shell 会当做重定向到一个文件名为 1 的文件中</strong></p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6127timestamp1523951876075.png" alt="此处输入图片的描述"></p>
<h3 id="使用-tee-命令同时重定向到多个文件"><a href="#使用-tee-命令同时重定向到多个文件" class="headerlink" title="使用 tee 命令同时重定向到多个文件"></a>使用 tee 命令同时重定向到多个文件</h3><p> 你可能还有这样的需求，除了需要将输出重定向到文件，也需要将信息打印在终端。那么你可以使用 <code>tee</code> 命令来实现：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &#x27;hello shiyanlou&#x27; | tee hello</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid346timestamp1532415315324.png" alt="此处输入图片的描述"></p>
<h3 id="永久重定向"><a href="#永久重定向" class="headerlink" title="永久重定向"></a>永久重定向</h3><p>你应该可以看出我们前面的重定向操作都只是临时性的，即只对当前命令有效，那如何做到永久有效呢，比如在一个脚本中，你需要某一部分的命令的输出全部进行重定向，难道要让你在每个命令上面加上临时重定向的操作嘛？</p>
<p>当然不需要，我们可以使用 <code>exec</code> 命令实现永久重定向。<code>exec</code> 命令的作用是使用指定的命令替换当前的 Shell，即使用一个进程替换当前进程，或者指定新的重定向：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 先开启一个子 Shell</span><br><span class="line">zsh</span><br><span class="line"># 使用exec替换当前进程的重定向，将标准输出重定向到一个文件</span><br><span class="line">exec 1&gt;somefile</span><br><span class="line"># 后面你执行的命令的输出都将被重定向到文件中，直到你退出当前子shell，或取消exec的重定向（后面将告诉你怎么做）</span><br><span class="line">ls</span><br><span class="line">exit</span><br><span class="line">cat somefile</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6127timestamp1523952144929.png" alt="此处输入图片的描述"></p>
<h3 id="创建输出文件描述符"><a href="#创建输出文件描述符" class="headerlink" title="创建输出文件描述符"></a>创建输出文件描述符</h3><p>在 Shell 中有 9 个文件描述符。上面我们使用了也是它默认提供的 0，1，2 号文件描述符。另外我们还可以使用 3-8 的文件描述符，只是它们默认没有打开而已。你可以使用下面命令查看当前 Shell 进程中打开的文件描述符：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd /dev/fd/;ls -Al</span><br></pre></td></tr></table></figure>

<p>同样使用 <code>exec</code> 命令可以创建新的文件描述符：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">zsh</span><br><span class="line">exec 3&gt;somefile</span><br><span class="line"># 先进入目录，再查看，否则你可能不能得到正确的结果，然后再回到上一次的目录</span><br><span class="line">cd /dev/fd/;ls -Al;cd -</span><br><span class="line"># 注意下面的命令&gt;与&amp;之间不应该有空格，如果有空格则会出错</span><br><span class="line">echo &quot;this is test&quot; &gt;&amp;3</span><br><span class="line">cat somefile</span><br><span class="line">exit</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid346timestamp1532415336263.png" alt="此处输入图片的描述"></p>
<h3 id="关闭文件描述符"><a href="#关闭文件描述符" class="headerlink" title="关闭文件描述符"></a>关闭文件描述符</h3><p>如上面我们打开的 3 号文件描述符，可以使用如下操作将它关闭：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">exec 3&gt;&amp;-</span><br><span class="line">cd /dev/fd;ls -Al;cd -</span><br></pre></td></tr></table></figure>

<h3 id="完全屏蔽命令的输出"><a href="#完全屏蔽命令的输出" class="headerlink" title="完全屏蔽命令的输出"></a>完全屏蔽命令的输出</h3><p>在 Linux 中有一个被称为黑洞的设备文件，所有导入它的数据都将被吞噬。</p>
<blockquote>
<p>在类 UNIX 系统中，&#x2F;dev&#x2F;null，或称空设备，是一个特殊的设备文件，它通常被用于丢弃不需要的输出流，或作为用于输入流的空文件，这些操作通常由重定向完成。读取它则会立即得到一个 EOF。</p>
</blockquote>
<p>我们可以利用 <code>/dev/null</code> 屏蔽命令的输出：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat Documents/test.c 1&gt;/dev/null 2&gt;&amp;1</span><br></pre></td></tr></table></figure>

<p>上面这样的操作将使你得不到任何输出结果。</p>
<h3 id="使用-xargs-分割参数列表"><a href="#使用-xargs-分割参数列表" class="headerlink" title="使用 xargs 分割参数列表"></a>使用 xargs 分割参数列表</h3><blockquote>
<p>xargs 是一条 UNIX 和类 UNIX 操作系统的常用命令。它的作用是将参数列表转换成小块分段传递给其他命令，以避免参数列表过长的问题。</p>
</blockquote>
<p>这个命令在有些时候十分有用，特别是当用来处理产生大量输出结果的命令如 <code>find</code>，<code>locate</code> 和 <code>grep</code> 的结果，详细用法请参看 man 文档。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cut -d: -f1 &lt; /etc/passwd | sort | xargs echo</span><br></pre></td></tr></table></figure>

<p>上面这个命令用于将 <code>/etc/passwd</code> 文件按 <code>:</code> 分割取第一个字段排序后，使用 <code>echo</code> 命令生成一个列表。</p>
<h1 id="正则表达式基础"><a href="#正则表达式基础" class="headerlink" title="正则表达式基础"></a>正则表达式基础</h1><h2 id="正则表达式"><a href="#正则表达式" class="headerlink" title="正则表达式"></a>正则表达式</h2><h3 id="基本语法"><a href="#基本语法" class="headerlink" title="基本语法"></a>基本语法</h3><p>一个正则表达式通常被称为一个模式（<strong>pattern</strong>），为用来描述或者匹配一系列符合某个句法规则的字符串。</p>
<h4 id="选择"><a href="#选择" class="headerlink" title="选择"></a>选择</h4><p><code>|</code> 竖直分隔符表示选择，例如 <code>boy|girl</code> 可以匹配 <code>boy</code> 或者 <code>girl</code>。</p>
<h4 id="数量限定"><a href="#数量限定" class="headerlink" title="数量限定"></a>数量限定</h4><p>数量限定除了我们举例用的 <code>*</code> 还有 <code>+</code> 加号 <code>?</code> 问号，如果在一个模式中不加数量限定符则表示出现一次且仅出现一次：</p>
<ul>
<li><code>+</code> 表示前面的字符必须出现至少一次(1 次或多次)，例如 <code>goo+gle</code> 可以匹配 <code>gooogle</code>，<code>goooogle</code> 等；</li>
<li><code>?</code> 表示前面的字符最多出现一次（0 次或 1 次），例如，<code>colou?r</code>，可以匹配 <code>color</code> 或者 <code>colour</code>;</li>
<li><code>*</code> 星号代表前面的字符可以不出现，也可以出现一次或者多次（0 次、或 1 次、或多次），例如，<code>0*42</code> 可以匹配 42、042、0042、00042 等。</li>
</ul>
<h4 id="范围和优先级"><a href="#范围和优先级" class="headerlink" title="范围和优先级"></a>范围和优先级</h4><p><code>()</code> 圆括号可以用来定义模式字符串的范围和优先级，这可以简单的理解为是否将括号内的模式串作为一个整体。例如，<code>gr(a|e)y</code> 等价于 <code>gray|grey</code>，（这里体现了优先级，竖直分隔符用于选择 <code>a</code> 或者 <code>e</code> 而不是 <code>gra</code> 和 <code>ey</code>），<code>(grand)?father</code> 匹配 <code>father</code> 和 <code>grandfather</code>（这里体现了范围，<code>?</code> 将圆括号内容作为一个整体匹配）。</p>
<h4 id="语法（部分）"><a href="#语法（部分）" class="headerlink" title="语法（部分）"></a>语法（部分）</h4><p>正则表达式有多种不同的风格，下面列举一些常用的作为 PCRE 子集的适用于 <code>perl</code> 和 <code>python</code> 编程语言及 <code>grep</code> 或 <code>egrep</code> 的正则表达式匹配规则：</p>
<blockquote>
<p>PCRE（Perl Compatible Regular Expressions 中文含义：perl 语言兼容正则表达式）是一个用 C 语言编写的正则表达式函数库，由菲利普.海泽(Philip Hazel)编写。PCRE 是一个轻量级的函数库，比 Boost 之类的正则表达式库小得多。PCRE 十分易用，同时功能也很强大，性能超过了 POSIX 正则表达式库和一些经典的正则表达式库。</p>
</blockquote>
<p><strong>(由于 markdown 表格解析的问题，下面的竖直分隔符 | 用全角字符代替，实际使用时请换回半角字符。</strong></p>
<table>
<thead>
<tr>
<th>字符</th>
<th>描述</th>
</tr>
</thead>
<tbody><tr>
<td><code>\</code></td>
<td><strong>将下一个字符标记为一个特殊字符、或一个原义字符。</strong> 例如 <code>n</code> 匹配字符 <code>n</code>。<code>\n</code> 匹配一个换行符。序列 <code>\\</code> 匹配 <code>\</code> 而 <code>\(</code> 则匹配 <code>(</code>。</td>
</tr>
<tr>
<td><code>^</code></td>
<td><strong>匹配输入字符串的开始位置。</strong></td>
</tr>
<tr>
<td><code>$</code></td>
<td><strong>匹配输入字符串的结束位置。</strong></td>
</tr>
<tr>
<td><code>&#123;n&#125;</code></td>
<td>n 是一个非负整数。<strong>匹配确定的 n 次</strong>。例如 <code>o&#123;2&#125;</code> 不能匹配 <code>Bob</code> 中的 <code>o</code>，但是能匹配 <code>food</code> 中的两个 <code>o</code>。</td>
</tr>
<tr>
<td><code>&#123;n,&#125;</code></td>
<td>n 是一个非负整数。<strong>至少匹配 n 次</strong>。例如 <code>o&#123;2,&#125;</code> 不能匹配 <code>Bob</code> 中的 <code>o</code>，但能匹配 <code>foooood</code> 中的所有 <code>o</code>。<code>o&#123;1,&#125;</code> 等价于 <code>o+</code>。<code>o&#123;0,&#125;</code> 则等价于 <code>o*</code>。</td>
</tr>
<tr>
<td><code>&#123;n,m&#125;</code></td>
<td>m 和 n 均为非负整数，其中 <code>n&lt;=m</code>。<strong>最少匹配 n 次且最多匹配 m 次</strong>。例如，<code>o&#123;1,3&#125;</code> 将匹配 <code>fooooood</code> 中的前三个 <code>o</code>。<code>o&#123;0,1&#125;</code> 等价于 <code>o?</code>。请注意在逗号和两个数之间不能有空格。</td>
</tr>
<tr>
<td><code>*</code></td>
<td><strong>匹配前面的子表达式零次或多次</strong>。例如，<code>zo*</code> 能匹配 <code>z</code>、<code>zo</code> 以及 <code>zoo</code>。<code>*</code> 等价于 <code>&#123;0,&#125;</code>。</td>
</tr>
<tr>
<td><code>+</code></td>
<td><strong>匹配前面的子表达式一次或多次</strong>。例如，<code>zo+</code> 能匹配 <code>zo</code> 以及 <code>zoo</code>，但不能匹配 <code>z</code>。<code>+</code> 等价于 <code>&#123;1,&#125;</code>。</td>
</tr>
<tr>
<td><code>?</code></td>
<td><strong>匹配前面的子表达式零次或一次</strong>。例如，<code>do(es)?</code> 可以匹配 <code>do</code> 或 <code>does</code> 中的 <code>do</code>。<code>?</code> 等价于 <code>&#123;0,1&#125;</code>。</td>
</tr>
<tr>
<td><code>?</code></td>
<td>当该字符紧跟在任何一个其他限制符（<code>*</code>，<code>+</code>，<code>?</code>，<code>&#123;n&#125;</code>，<code>&#123;n,&#125;</code>，<code>&#123;n,m&#125;</code>）后面时，匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串，而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如，对于字符串 <code>oooo</code>，<code>o+?</code> 将匹配单个 <code>o</code>，而 <code>o+</code> 将匹配所有 <code>o</code>。</td>
</tr>
<tr>
<td><code>.</code></td>
<td><strong>匹配除 \n 之外的任何单个字符</strong>。要匹配包括 <code>\n</code> 在内的任何字符，请使用类似 <code>(.｜\n)</code> 的模式。</td>
</tr>
<tr>
<td><code>(pattern)</code></td>
<td><strong>匹配 pattern 并获取这一匹配的子字符串</strong>。该子字符串用于向后引用。要匹配圆括号字符，请使用 <code>\(</code> 和 <code>\)</code>。</td>
</tr>
<tr>
<td>&#96;x</td>
<td>y&#96;</td>
</tr>
<tr>
<td><code>[xyz]</code></td>
<td>字符集合（character class）。<strong>匹配所包含的任意一个字符</strong>。例如，<code>[abc]</code> 可以匹配 <code>plain</code> 中的 <code>a</code>。其中特殊字符仅有反斜线 <code>\</code> 保持特殊含义，用于转义字符。其它特殊字符如星号、加号、各种括号等均作为普通字符。脱字符^如果出现在首位则表示负值字符集合；如果出现在字符串中间就仅作为普通字符。<strong>连字符 - 如果出现在字符串中间表示字符范围描述；如果出现在首位则仅作为普通字符。</strong></td>
</tr>
<tr>
<td><code>[^xyz]</code></td>
<td>排除型（negate）字符集合。<strong>匹配未列出的任意字符。</strong>例如，<code>[^abc]</code> 可以匹配 <code>plain</code> 中的 <code>plin</code>。</td>
</tr>
<tr>
<td><code>[a-z]</code></td>
<td>字符范围。<strong>匹配指定范围内的任意字符。</strong>例如，<code>[a-z]</code> 可以匹配 <code>a</code> 到 <code>z</code> 范围内的任意小写字母字符。</td>
</tr>
<tr>
<td><code>[^a-z]</code></td>
<td>排除型的字符范围。<strong>匹配任何不在指定范围内的任意字符</strong>。例如，<code>[^a-z]</code> 可以匹配任何不在 <code>a</code> 到 <code>z</code> 范围内的任意字符。</td>
</tr>
</tbody></table>
<h4 id="优先级"><a href="#优先级" class="headerlink" title="优先级"></a>优先级</h4><p>优先级为从上到下从左到右，依次降低：</p>
<table>
<thead>
<tr>
<th>运算符</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>\</code></td>
<td>转义符</td>
</tr>
<tr>
<td><code>()</code>，<code>(?:)</code>，<code>(?=)</code>，<code>[]</code></td>
<td>括号和中括号</td>
</tr>
<tr>
<td><code>*</code>，<code>+</code>，<code>?</code>，<code>&#123;n&#125;</code>，<code>&#123;n,&#125;</code>，<code>&#123;n,m&#125;</code></td>
<td>限定符</td>
</tr>
<tr>
<td><code>^</code>，<code>$</code>，<code>\</code> 任何元字符</td>
<td>定位点和序列</td>
</tr>
<tr>
<td>｜</td>
<td>选择</td>
</tr>
</tbody></table>
<p>更多正则表达式的内容可以参考以下链接：</p>
<ul>
<li><a target="_blank" rel="noopener" href="http://zh.wikipedia.org/wiki/%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F">正则表达式 wiki</a></li>
<li><a target="_blank" rel="noopener" href="http://www.greenend.org.uk/rjk/tech/regexp.html">几种正则表达式引擎的语法差异</a></li>
<li><a target="_blank" rel="noopener" href="http://en.wikipedia.org/wiki/Comparison_of_regular_expression_engines">各语言各平台对正则表达式的支持</a></li>
</ul>
<p>regex 的思导图：</p>
<p><img src="https://doc.shiyanlou.com/linux_base/RegularExpression.png" alt="pic"></p>
<h2 id="grep-模式匹配命令"><a href="#grep-模式匹配命令" class="headerlink" title="grep 模式匹配命令"></a>grep 模式匹配命令</h2><h3 id="基本操作-1"><a href="#基本操作-1" class="headerlink" title="基本操作"></a>基本操作</h3><p><code>grep</code> 命令用于打印输出文本中匹配的模式串，它使用正则表达式作为模式匹配的条件。<code>grep</code> 支持三种正则表达式引擎，分别用三个参数指定：</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-E</code></td>
<td>POSIX 扩展正则表达式，ERE</td>
</tr>
<tr>
<td><code>-G</code></td>
<td>POSIX 基本正则表达式，BRE</td>
</tr>
<tr>
<td><code>-P</code></td>
<td>Perl 正则表达式，PCRE</td>
</tr>
</tbody></table>
<p>不过在你没学过 perl 语言的大多数情况下你将只会使用到 <code>ERE</code> 和 <code>BRE</code>，所以我们接下来的内容都不会讨论到 PCRE 中特有的一些正则表达式语法（它们之间大部分内容是存在交集的，所以你不用担心会遗漏多少重要内容）。</p>
<p>在通过<code>grep</code>命令使用正则表达式之前，先介绍一下它的常用参数：</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-b</code></td>
<td>将二进制文件作为文本来进行匹配</td>
</tr>
<tr>
<td><code>-c</code></td>
<td>统计以模式匹配的数目</td>
</tr>
<tr>
<td><code>-i</code></td>
<td>忽略大小写</td>
</tr>
<tr>
<td><code>-n</code></td>
<td>显示匹配文本所在行的行号</td>
</tr>
<tr>
<td><code>-v</code></td>
<td>反选，输出不匹配行的内容</td>
</tr>
<tr>
<td><code>-r</code></td>
<td>递归匹配查找</td>
</tr>
<tr>
<td><code>-A n</code></td>
<td>n 为正整数，表示 after 的意思，除了列出匹配行之外，还列出后面的 n 行</td>
</tr>
<tr>
<td><code>-B n</code></td>
<td>n 为正整数，表示 before 的意思，除了列出匹配行之外，还列出前面的 n 行</td>
</tr>
<tr>
<td><code>--color=auto</code></td>
<td>将输出中的匹配项设置为自动颜色显示</td>
</tr>
</tbody></table>
<blockquote>
<p>注：在大多数发行版中是默认设置了 grep 的颜色的，你可以通过参数指定或修改<code>GREP_COLOR</code>环境变量。</p>
</blockquote>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415381859.png" alt="此处输入图片的描述"></p>
<h3 id="使用正则表达式"><a href="#使用正则表达式" class="headerlink" title="使用正则表达式"></a>使用正则表达式</h3><h4 id="使用基本正则表达式，BRE"><a href="#使用基本正则表达式，BRE" class="headerlink" title="使用基本正则表达式，BRE"></a>使用基本正则表达式，BRE</h4><ul>
<li>位置</li>
</ul>
<p>查找 <code>/etc/group</code> 文件中以 <code>shiyanlou</code> 为开头的行</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">grep &#x27;shiyanlou&#x27; /etc/group</span><br><span class="line">grep &#x27;^shiyanlou&#x27; /etc/group</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid600404labid6128timestamp1523954676432.png" alt="此处输入图片的描述"></p>
<ul>
<li>数量</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 将匹配以&#x27;z&#x27;开头以&#x27;o&#x27;结尾的所有字符串</span><br><span class="line">echo &#x27;zero\nzo\nzoo&#x27; | grep &#x27;z.*o&#x27;</span><br><span class="line"># 将匹配以&#x27;z&#x27;开头以&#x27;o&#x27;结尾，中间包含一个任意字符的字符串</span><br><span class="line">echo &#x27;zero\nzo\nzoo&#x27; | grep &#x27;z.o&#x27;</span><br><span class="line"># 将匹配以&#x27;z&#x27;开头，以任意多个&#x27;o&#x27;结尾的字符串</span><br><span class="line">echo &#x27;zero\nzo\nzoo&#x27; | grep &#x27;zo*&#x27;</span><br></pre></td></tr></table></figure>

<p>注意：其中 <code>\n</code> 为换行符</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415422642.png" alt="此处输入图片的描述"></p>
<ul>
<li>选择</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"># grep默认是区分大小写的，这里将匹配所有的小写字母</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[a-z]&#x27;</span><br><span class="line"># 将匹配所有的数字</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[0-9]&#x27;</span><br><span class="line"># 将匹配所有的数字</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[[:digit:]]&#x27;</span><br><span class="line"># 将匹配所有的小写字母</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[[:lower:]]&#x27;</span><br><span class="line"># 将匹配所有的大写字母</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[[:upper:]]&#x27;</span><br><span class="line"># 将匹配所有的字母和数字，包括0-9，a-z，A-Z</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[[:alnum:]]&#x27;</span><br><span class="line"># 将匹配所有的字母</span><br><span class="line">echo &#x27;1234\nabcd&#x27; | grep &#x27;[[:alpha:]]&#x27;</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415449222.png" alt="此处输入图片的描述"></p>
<p>下面包含完整的特殊符号及说明：</p>
<table>
<thead>
<tr>
<th>特殊符号</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>[:alnum:]</code></td>
<td>代表英文大小写字母及数字，亦即 0-9，A-Z，a-z</td>
</tr>
<tr>
<td><code>[:alpha:]</code></td>
<td>代表任何英文大小写字母，亦即 A-Z，a-z</td>
</tr>
<tr>
<td><code>[:blank:]</code></td>
<td>代表空白键与 <code>[Tab]</code> 按键两者</td>
</tr>
<tr>
<td><code>[:cntrl:]</code></td>
<td>代表键盘上面的控制按键，亦即包括 CR，LF，Tab，Del…</td>
</tr>
<tr>
<td><code>[:digit:]</code></td>
<td>代表数字而已，亦即 0-9</td>
</tr>
<tr>
<td><code>[:graph:]</code></td>
<td>除了空白字节（空白键与 [Tab] 按键）外的其他所有按键</td>
</tr>
<tr>
<td><code>[:lower:]</code></td>
<td>代表小写字母，亦即 a-z</td>
</tr>
<tr>
<td><code>[:print:]</code></td>
<td>代表任何可以被列印出来的字符</td>
</tr>
<tr>
<td><code>[:punct:]</code></td>
<td>代表标点符号（punctuation symbol），即：<code>&quot;</code>，<code>&#39;</code>，<code>?</code>，<code>!</code>，<code>;</code>，<code>:</code>，<code>#</code>，<code>$</code>…</td>
</tr>
<tr>
<td><code>[:upper:]</code></td>
<td>代表大写字母，亦即 A-Z</td>
</tr>
<tr>
<td><code>[:space:]</code></td>
<td>任何会产生空白的字符，包括空格键，<code>[Tab]</code>，CR 等等</td>
</tr>
<tr>
<td><code>[:xdigit:]</code></td>
<td>代表 16 进位的数字类型，因此包括： 0-9，A-F，a-f 的数字与字节</td>
</tr>
</tbody></table>
<blockquote>
<p><strong>注意</strong>：之所以要使用特殊符号，是因为上面的 <code>[a-z]</code> 不是在所有情况下都管用，这还与主机当前的语系有关，即设置在 <code>LANG</code> 环境变量的值，<code>zh_CN.UTF-8</code> 的话 <code>[a-z]</code>，即为所有小写字母，其它语系可能是大小写交替的如，”a A b B…z Z”，<code>[a-z]</code> 中就可能包含大写字母。所以在使用 <code>[a-z]</code> 时请确保当前语系的影响，使用 <code>[:lower:]</code> 则不会有这个问题。</p>
</blockquote>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 排除字符</span><br><span class="line">echo &#x27;geek\ngood&#x27; | grep &#x27;[^o]&#x27;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>当 <code>^</code> 放到中括号内为排除字符，否则表示行首。</p>
</blockquote>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415467268.png" alt="此处输入图片的描述"></p>
<h4 id="使用扩展正则表达式，ERE"><a href="#使用扩展正则表达式，ERE" class="headerlink" title="使用扩展正则表达式，ERE"></a>使用扩展正则表达式，ERE</h4><p>要通过 <code>grep</code> 使用扩展正则表达式需要加上 <code>-E</code> 参数，或使用 <code>egrep</code>。</p>
<ul>
<li>数量</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 只匹配&quot;zo&quot;</span><br><span class="line">echo &#x27;zero\nzo\nzoo&#x27; | grep -E &#x27;zo&#123;1&#125;&#x27;</span><br><span class="line"># 匹配以&quot;zo&quot;开头的所有单词</span><br><span class="line">echo &#x27;zero\nzo\nzoo&#x27; | grep -E &#x27;zo&#123;1,&#125;&#x27;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>推荐掌握 <code>&#123;n,m&#125;</code> 即可 <code>+</code>，<code>?</code>，<code>*</code> 这几个不太直观，且容易弄混淆。</p>
</blockquote>
<ul>
<li>选择</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 匹配&quot;www.shiyanlou.com&quot;和&quot;www.google.com&quot;</span><br><span class="line">echo &#x27;www.shiyanlou.com\nwww.baidu.com\nwww.google.com&#x27; | grep -E &#x27;www\.(shiyanlou|google)\.com&#x27;</span><br><span class="line"># 或者匹配不包含&quot;baidu&quot;的内容</span><br><span class="line">echo &#x27;www.shiyanlou.com\nwww.baidu.com\nwww.google.com&#x27; | grep -Ev &#x27;www\.baidu\.com&#x27;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>因为 <code>.</code> 号有特殊含义，所以需要转义。</p>
</blockquote>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415579510.png" alt="此处输入图片的描述"></p>
<p>关于正则表达式和 <code>grep</code> 命令的内容就介绍这么多，下面会介绍两个更强大的工具 <code>sed</code> 和 <code>awk</code>，但同样也正是因为这两个工具的强大，我们的内容无法包含它们的全部，这里将只对基本内容作介绍。</p>
<h2 id="sed-流编辑器"><a href="#sed-流编辑器" class="headerlink" title="sed 流编辑器"></a>sed 流编辑器</h2><p><code>sed</code> 工具在 man 手册里面的全名为”sed - stream editor for filtering and transforming text “，意即，用于过滤和转换文本的流编辑器。</p>
<p>在 Linux&#x2F;UNIX 的世界里敢称为编辑器的工具，大都非等闲之辈，比如前面的 <code>vi/vim</code>（编辑器之神），<code>emacs</code>（神的编辑器），<code>gedit</code> 这些编辑器。<code>sed</code> 与上述的最大不同之处在于它是一个非交互式的编辑器，下面我们就开始介绍 <code>sed</code> 这个编辑器。</p>
<h3 id="sed-常用参数介绍"><a href="#sed-常用参数介绍" class="headerlink" title="sed 常用参数介绍"></a>sed 常用参数介绍</h3><p>sed 命令基本格式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">sed [参数]... [执行命令] [输入文件]...</span><br><span class="line"># 形如：</span><br><span class="line">$ sed -i &#x27;s/sad/happy/&#x27; test # 表示将test文件中的&quot;sad&quot;替换为&quot;happy&quot;</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-n</code></td>
<td>安静模式，只打印受影响的行，默认打印输入数据的全部内容</td>
</tr>
<tr>
<td><code>-e</code></td>
<td>用于在脚本中添加多个执行命令一次执行，在命令行中执行多个命令通常不需要加该参数</td>
</tr>
<tr>
<td><code>-f filename</code></td>
<td>指定执行 filename 文件中的命令</td>
</tr>
<tr>
<td><code>-r</code></td>
<td>使用扩展正则表达式，默认为标准正则表达式</td>
</tr>
<tr>
<td><code>-i</code></td>
<td>将直接修改输入文件内容，而不是打印到标准输出设备</td>
</tr>
</tbody></table>
<h3 id="sed-编辑器的执行命令（这里”执行“解释为名词）"><a href="#sed-编辑器的执行命令（这里”执行“解释为名词）" class="headerlink" title="sed 编辑器的执行命令（这里”执行“解释为名词）"></a>sed 编辑器的执行命令（这里”执行“解释为名词）</h3><p>sed 执行命令格式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[n1][,n2]command</span><br><span class="line">[n1][~step]command</span><br></pre></td></tr></table></figure>

<p>其中一些命令可以在后面加上作用范围，形如：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sed -i &#x27;s/sad/happy/g&#x27; test # g 表示全局范围</span><br><span class="line">sed -i &#x27;s/sad/happy/4&#x27; test # 4 表示指定行中的第四个匹配字符串</span><br></pre></td></tr></table></figure>

<p>其中 <code>n1,n2</code> 表示输入内容的行号，它们之间为 <code>,</code> 逗号则表示从 n1 到 n2 行，如果为 <code>~</code> 波浪号则表示从 n1 开始以 step 为步进的所有行；command 为执行动作，下面为一些常用动作指令：</p>
<table>
<thead>
<tr>
<th>命令</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>s</code></td>
<td>行内替换</td>
</tr>
<tr>
<td><code>c</code></td>
<td>整行替换</td>
</tr>
<tr>
<td><code>a</code></td>
<td>插入到指定行的后面</td>
</tr>
<tr>
<td><code>i</code></td>
<td>插入到指定行的前面</td>
</tr>
<tr>
<td><code>p</code></td>
<td>打印指定行，通常与 <code>-n</code> 参数配合使用</td>
</tr>
<tr>
<td><code>d</code></td>
<td>删除指定行</td>
</tr>
</tbody></table>
<h3 id="sed-操作举例"><a href="#sed-操作举例" class="headerlink" title="sed 操作举例"></a>sed 操作举例</h3><p>我们先找一个用于练习的文本文件：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cp /etc/passwd ~</span><br></pre></td></tr></table></figure>

<h4 id="打印指定行"><a href="#打印指定行" class="headerlink" title="打印指定行"></a>打印指定行</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"># 打印2-5行</span><br><span class="line">nl passwd | sed -n &#x27;2,5p&#x27;</span><br><span class="line"># 打印奇数行</span><br><span class="line">nl passwd | sed -n &#x27;1~2p&#x27;</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415685031.png" alt="此处输入图片的描述"></p>
<h4 id="行内替换"><a href="#行内替换" class="headerlink" title="行内替换"></a>行内替换</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 将输入文本中&quot;shiyanlou&quot; 全局替换为&quot;hehe&quot;，并只打印替换的那一行，注意这里不能省略最后的&quot;p&quot;命令</span><br><span class="line">sed -n &#x27;s/shiyanlou/hehe/gp&#x27; passwd</span><br></pre></td></tr></table></figure>

<blockquote>
<p>行内替换可以结合正则表达式使用。</p>
</blockquote>
<h4 id="删除某行"><a href="#删除某行" class="headerlink" title="删除某行"></a>删除某行</h4><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">nl passwd | grep &quot;shiyanlou&quot;</span><br><span class="line"># 删除第30行</span><br><span class="line">sed -i &#x27;30d&#x27; passwd</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid600404-20191015-1571118544931" alt="图片描述"></p>
<p>关于 sed 命令就介绍这么多，你如果希望了解更多 sed 的高级用法，你可以参看如下链接：</p>
<ul>
<li><a target="_blank" rel="noopener" href="http://coolshell.cn/articles/9104.html">sed 简明教程</a></li>
<li><a target="_blank" rel="noopener" href="http://sed.sourceforge.net/sed1line_zh-CN.html">sed 单行脚本快速参考</a></li>
<li><a target="_blank" rel="noopener" href="http://www.gnu.org/software/sed/manual/sed.html">sed 完全手册</a></li>
</ul>
<h2 id="awk-文本处理语言"><a href="#awk-文本处理语言" class="headerlink" title="awk 文本处理语言"></a>awk 文本处理语言</h2><h3 id="awk-介绍"><a href="#awk-介绍" class="headerlink" title="awk 介绍"></a>awk 介绍</h3><p>AWK 是一种优良的文本处理工具，Linux 及 Unix 环境中现有的功能最强大的数据处理引擎之一。其名称得自于它的创始人 Alfred Aho（阿尔佛雷德·艾侯）、Peter Jay Weinberger（彼得·温伯格）和 Brian Wilson Kernighan（布莱恩·柯林汉)姓氏的首个字母 <code>AWK</code>，三位创建者已将它正式定义为“样式扫描和处理语言”。它允许你创建简短的程序，这些程序读取输入文件、为数据排序、处理数据、对输入执行计算以及生成报表，还有无数其他的功能。最简单地说，AWK 是一种用于处理文本的编程语言工具。</p>
<p>在大多数 Linux 发行版上面，实际我们使用的是 gawk（GNU awk，awk 的 GNU 版本），在我们的环境中 ubuntu 上，默认提供的是 mawk，不过我们通常可以直接使用 awk 命令（awk 语言的解释器），因为系统已经为我们创建好了 awk 指向 mawk 的符号链接。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ll /usr/bin/awk</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532416617431.png" alt="此处输入图片的描述"></p>
<blockquote>
<p>nawk： 在 20 世纪 80 年代中期，对 awk 语言进行了更新，并不同程度地使用一种称为 nawk(new awk) 的增强版本对其进行了替换。许多系统中仍然存在着旧的 awk 解释器，但通常将其安装为 oawk (old awk) 命令，而 nawk 解释器则安装为主要的 awk 命令，也可以使用 nawk 命令。Dr. Kernighan 仍然在对 nawk 进行维护，与 gawk 一样，它也是开放源代码的，并且可以免费获得;</p>
</blockquote>
<blockquote>
<p>gawk： 是 GNU Project 的 awk 解释器的开放源代码实现。尽管早期的 GAWK 发行版是旧的 AWK 的替代程序，但不断地对其进行了更新，以包含 NAWK 的特性;</p>
</blockquote>
<blockquote>
<p>mawk 也是 awk 编程语言的一种解释器，mawk 遵循 POSIX 1003.2 （草案 11.3）定义的 AWK 语言，包含了一些没有在 AWK 手册中提到的特色，同时 mawk 提供一小部分扩展，另外据说 mawk 是实现最快的 awk。</p>
</blockquote>
<h3 id="awk-的一些基础概念"><a href="#awk-的一些基础概念" class="headerlink" title="awk 的一些基础概念"></a>awk 的一些基础概念</h3><p>awk 所有的操作都是基于 pattern(模式)—action(动作)对来完成的，如下面的形式：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pattern &#123;action&#125;</span><br></pre></td></tr></table></figure>

<p>你可以看到就如同很多编程语言一样，它将所有的动作操作用一对 <code>&#123;&#125;</code> 花括号包围起来。其中 pattern 通常是表示用于匹配输入的文本的“关系式”或“正则表达式”，action 则是表示匹配后将执行的动作。在一个完整 awk 操作中，这两者可以只有其中一个，如果没有 pattern 则默认匹配输入的全部文本，如果没有 action 则默认为打印匹配内容到屏幕。</p>
<p><code>awk</code> 处理文本的方式，是将文本分割成一些“字段”，然后再对这些字段进行处理，默认情况下，awk 以空格作为一个字段的分割符，不过这不是固定的，你可以任意指定分隔符，下面将告诉你如何做到这一点。</p>
<h3 id="awk-命令基本格式"><a href="#awk-命令基本格式" class="headerlink" title="awk 命令基本格式"></a>awk 命令基本格式</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">awk [-F fs] [-v var=value] [-f prog-file | &#x27;program text&#x27;] [file...]</span><br></pre></td></tr></table></figure>

<p>其中 <code>-F</code> 参数用于预先指定前面提到的字段分隔符（还有其他指定字段的方式），<code>-v</code> 用于预先为 <code>awk</code> 程序指定变量，<code>-f</code> 参数用于指定 <code>awk</code> 命令要执行的程序文件，或者在不加 <code>-f</code> 参数的情况下直接将程序语句放在这里，最后为 <code>awk</code> 需要处理的文本输入，且可以同时输入多个文本文件。现在我们还是直接来具体体验一下吧。</p>
<h3 id="awk-操作体验"><a href="#awk-操作体验" class="headerlink" title="awk 操作体验"></a>awk 操作体验</h3><p>先用 vim 新建一个文本文档：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim test</span><br></pre></td></tr></table></figure>

<p>包含如下内容：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">I like linux</span><br><span class="line">www.shiyanlou.com</span><br></pre></td></tr></table></figure>

<ul>
<li>使用 awk 将文本内容打印到终端：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># &quot;quote&gt;&quot; 不用输入</span><br><span class="line">awk &#x27;&#123;</span><br><span class="line">quote&gt; print</span><br><span class="line">quote&gt; &#125;&#x27; test</span><br><span class="line"># 或者写到一行</span><br><span class="line">awk &#x27;&#123;print&#125;&#x27; test</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415757042.png" alt="此处输入图片的描述"></p>
<p>说明:在这个操作中我是省略了 <code>pattern</code>，所以 <code>awk</code> 会默认匹配输入文本的全部内容，然后在 <code>&#123;&#125;</code> 花括号中执行动作，即 <code>print</code> 打印所有匹配项，这里是全部文本内容。</p>
<ul>
<li>将 test 的第一行的每个字段单独显示为一行：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">$ awk &#x27;&#123;</span><br><span class="line">&gt; if(NR==1)&#123;</span><br><span class="line">&gt; print $1 &quot;\n&quot; $2 &quot;\n&quot; $3</span><br><span class="line">&gt; &#125; else &#123;</span><br><span class="line">&gt; print&#125;</span><br><span class="line">&gt; &#125;&#x27; test</span><br><span class="line"></span><br><span class="line"># 或者</span><br><span class="line">$ awk &#x27;&#123;</span><br><span class="line">&gt; if(NR==1)&#123;</span><br><span class="line">&gt; OFS=&quot;\n&quot;</span><br><span class="line">&gt; print $1, $2, $3</span><br><span class="line">&gt; &#125; else &#123;</span><br><span class="line">&gt; print&#125;</span><br><span class="line">&gt; &#125;&#x27; test</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415834591.png" alt="此处输入图片的描述"></p>
<p>说明:你首先应该注意的是，这里我使用了 <code>awk</code> 语言的分支选择语句<code>if</code>，它的使用和很多高级语言如 <code>C/C++</code> 语言基本一致，如果你有这些语言的基础，这里将很好理解。另一个你需要注意的是 <code>NR</code> 与 <code>OFS</code>，这两个是 <code>awk</code> 内建的变量，<code>NR</code> 表示当前读入的记录数，你可以简单的理解为当前处理的行数，<code>OFS</code> 表示输出时的字段分隔符，默认为” “空格，如上图所见，我们将字段分隔符设置为 <code>\n</code> 换行符，所以第一行原本以空格为字段分隔的内容就分别输出到单独一行了。然后是 <code>$N</code> 其中 N 为相应的字段号，这也是 <code>awk</code> 的内建变量，它表示引用相应的字段，因为我们这里第一行只有三个字段，所以只引用到了 <code>$3</code>。除此之外另一个这里没有出现的 <code>$0</code>，它表示引用当前记录（当前行）的全部内容。</p>
<ul>
<li>将 test 的第二行的以点为分段的字段换成以空格为分隔：</li>
</ul>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">awk -F&#x27;.&#x27; &#x27;&#123;</span><br><span class="line">&gt; if(NR==2)&#123;</span><br><span class="line">&gt; print $1 &quot;\t&quot; $2 &quot;\t&quot; $3</span><br><span class="line">&gt; &#125;&#125;&#x27; test</span><br><span class="line"></span><br><span class="line"># 或者</span><br><span class="line">awk &#x27;</span><br><span class="line">&gt; BEGIN&#123;</span><br><span class="line">&gt; FS=&quot;.&quot;</span><br><span class="line">&gt; OFS=&quot;\t&quot;  # 如果写为一行，两个动作语句之间应该以&quot;;&quot;号分开</span><br><span class="line">&gt; &#125;&#123;</span><br><span class="line">&gt; if(NR==2)&#123;</span><br><span class="line">&gt; print $1, $2, $3</span><br><span class="line">&gt; &#125;&#125;&#x27; test</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid354timestamp1532415838840.png" alt="此处输入图片的描述"></p>
<p>说明：这里的 <code>-F</code> 参数，前面已经介绍过，它是用来预先指定待处理记录的字段分隔符。我们需要注意的是除了指定 <code>OFS</code> 我们还可以在 <code>print</code> 语句中直接打印特殊符号如这里的 <code>\t</code>，<strong>print 打印的非变量内容都需要用””一对引号包围起来</strong>。上面另一个版本，展示了实现预先指定变量分隔符的另一种方式，即使用 <code>BEGIN</code>，就这个表达式指示了，其后的动作将在所有动作之前执行，这里是 <code>FS</code> 赋值了新的 <code>.</code> 点号代替默认的空格。</p>
<p><strong>注意</strong>:首先说明一点，我们在学习和使用 awk 的时候应该尽可能将其作为一门程序语言来理解，这样将会使你学习起来更容易，所以初学阶段在练习 <code>awk</code> 时应该尽量按照我那样的方式分多行按照一般程序语言的换行和缩进来输入，而不是全部写到一行（当然这在你熟练了之后是没有任何问题的）。</p>
<h3 id="awk-常用的内置变量"><a href="#awk-常用的内置变量" class="headerlink" title="awk 常用的内置变量"></a>awk 常用的内置变量</h3><table>
<thead>
<tr>
<th>变量名</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>FILENAME</code></td>
<td>当前输入文件名，若有多个文件，则只表示第一个。如果输入是来自标准输入，则为空字符串</td>
</tr>
<tr>
<td><code>$0</code></td>
<td>当前记录的内容</td>
</tr>
<tr>
<td><code>$N</code></td>
<td>N 表示字段号，最大值为<code>NF</code>变量的值</td>
</tr>
<tr>
<td><code>FS</code></td>
<td>字段分隔符，由正则表达式表示，默认为空格</td>
</tr>
<tr>
<td><code>RS</code></td>
<td>输入记录分隔符，默认为 <code>\n</code>，即一行为一个记录</td>
</tr>
<tr>
<td><code>NF</code></td>
<td>当前记录字段数</td>
</tr>
<tr>
<td><code>NR</code></td>
<td>已经读入的记录数</td>
</tr>
<tr>
<td><code>FNR</code></td>
<td>当前输入文件的记录数，请注意它与 NR 的区别</td>
</tr>
<tr>
<td><code>OFS</code></td>
<td>输出字段分隔符，默认为空格</td>
</tr>
<tr>
<td><code>ORS</code></td>
<td>输出记录分隔符，默认为 <code>\n</code></td>
</tr>
</tbody></table>
<p>关于<code>awk</code>的内容本课程将只会包含这些内容，如果你想了解更多，请期待后续课程，或者参看一下链接内容：</p>
<ul>
<li><a target="_blank" rel="noopener" href="http://awk.readthedocs.org/en/latest/chapter-one.html">awk 程序设计语言</a></li>
<li><a target="_blank" rel="noopener" href="http://coolshell.cn/articles/9070.html">awk 简明教程</a></li>
<li><a target="_blank" rel="noopener" href="http://www.gnu.org/software/gawk/manual/gawk.html">awk 用户指南</a></li>
</ul>
<h1 id="Linux-下软件安装"><a href="#Linux-下软件安装" class="headerlink" title="Linux 下软件安装"></a>Linux 下软件安装</h1><h2 id="开始-1"><a href="#开始-1" class="headerlink" title="开始"></a>开始</h2><h3 id="先体验一下"><a href="#先体验一下" class="headerlink" title="先体验一下"></a>先体验一下</h3><p>比如我们想安装一个软件，名字叫做 <code>w3m</code>(w3m 是一个命令行的简易网页浏览器)，那么输入如下命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install w3m -y</span><br></pre></td></tr></table></figure>

<p>这样的操作你应该在前面的章节中看到过很多次了，它就表示将会安装一个软件包名为 <code>w3m</code> 的软件。</p>
<p>我们来看看命令执行后的效果：</p>
<p><img src="https://doc.shiyanlou.com/courses/5673/1700764/f8f335bf157a7e63b5fbf62ed760ef89-0" alt="图片描述"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">w3m https://www.lanqiao.cn/faq</span><br></pre></td></tr></table></figure>

<p><strong>注意</strong>:如果你在安装一个软件之后，无法立即使用 <code>Tab</code> 键补全这个命令，你可以尝试先执行 <code>source ~/.zshrc</code>，然后你就可以使用补全操作。</p>
<p><img src="https://doc.shiyanlou.com/courses/1/1700764/a1d5a1fdb56a9c3554e92d13bebc03a8-0" alt="图片描述"></p>
<h3 id="apt-包管理工具介绍"><a href="#apt-包管理工具介绍" class="headerlink" title="apt 包管理工具介绍"></a>apt 包管理工具介绍</h3><blockquote>
<p>APT 是 Advance Packaging Tool（高级包装工具）的缩写，是 Debian 及其派生发行版的软件包管理器，APT 可以自动下载，配置，安装二进制或者源代码格式的软件包，因此简化了 Unix 系统上管理软件的过程。APT 最早被设计成 dpkg 的前端，用来处理 deb 格式的软件包。现在经过 APT-RPM 组织修改，APT 已经可以安装在支持 RPM 的系统管理 RPM 包。这个包管理器包含以 <code>apt-</code> 开头的多个工具，如 <code>apt-get</code> <code>apt-cache</code> <code>apt-cdrom</code> 等，在 Debian 系列的发行版中使用。</p>
</blockquote>
<p>当你在执行安装操作时，首先 <code>apt-get</code> 工具会在<strong>本地</strong>的一个数据库中搜索关于 <code>w3m</code> 软件的相关信息，并根据这些信息在相关的服务器上下载软件安装，这里大家可能会一个疑问：既然是在线安装软件，为啥会在本地的数据库中搜索？要解释这个问题就得提到几个名词了：</p>
<ul>
<li><strong>软件源镜像服务器</strong></li>
<li><strong>软件源</strong></li>
</ul>
<p>我们需要定期从服务器上下载一个软件包列表，使用 <code>sudo apt-get update</code> 命令来保持本地的软件包列表是最新的（有时你也需要手动执行这个操作，比如更换了软件源），而这个表里会有<strong>软件依赖</strong>信息的记录，对于软件依赖，我举个例子：我们安装 <code>w3m</code> 软件的时候，而这个软件需要 <code>libgc1c2</code> 这个软件包才能正常工作，这个时候 <code>apt-get</code> 在安装软件的时候会一并替我们安装了，以保证 <code>w3m</code> 能正常的工作。</p>
<h3 id="apt-get"><a href="#apt-get" class="headerlink" title="apt-get"></a>apt-get</h3><p><code>apt-get</code> 是用于处理 <code>apt</code>包的公用程序集，我们可以用它来在线安装、卸载和升级软件包等，下面列出一些 <code>apt-get</code> 包含的常用的一些工具：</p>
<table>
<thead>
<tr>
<th>工具</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>install</code></td>
<td>其后加上软件包名，用于安装一个软件包</td>
</tr>
<tr>
<td><code>update</code></td>
<td>从软件源镜像服务器上下载&#x2F;更新用于更新本地软件源的软件包列表</td>
</tr>
<tr>
<td><code>upgrade</code></td>
<td>升级本地可更新的全部软件包，但存在依赖问题时将不会升级，通常会在更新之前执行一次 <code>update</code></td>
</tr>
<tr>
<td><code>dist-upgrade</code></td>
<td>解决依赖关系并升级（存在一定危险性）</td>
</tr>
<tr>
<td><code>remove</code></td>
<td>移除已安装的软件包，包括与被移除软件包有依赖关系的软件包，但不包含软件包的配置文件</td>
</tr>
<tr>
<td><code>autoremove</code></td>
<td>移除之前被其他软件包依赖，但现在不再被使用的软件包</td>
</tr>
<tr>
<td><code>purge</code></td>
<td>与 remove 相同，但会完全移除软件包，包含其配置文件</td>
</tr>
<tr>
<td><code>clean</code></td>
<td>移除下载到本地的已经安装的软件包，默认保存在 <code>/var/cache/apt/archives/</code></td>
</tr>
<tr>
<td><code>autoclean</code></td>
<td>移除已安装的软件的旧版本软件包</td>
</tr>
</tbody></table>
<p>下面是一些<code>apt-get</code>常用的参数：</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-y</code></td>
<td>自动回应是否安装软件包的选项，在一些自动化安装脚本中使用这个参数将十分有用</td>
</tr>
<tr>
<td><code>-s</code></td>
<td>模拟安装</td>
</tr>
<tr>
<td><code>-q</code></td>
<td>静默安装方式，指定多个 <code>q</code> 或者 <code>-q=#</code>，<code>#</code> 表示数字，用于设定静默级别，这在你不想要在安装软件包时屏幕输出过多时很有用</td>
</tr>
<tr>
<td><code>-f</code></td>
<td>修复损坏的依赖关系</td>
</tr>
<tr>
<td><code>-d</code></td>
<td>只下载不安装</td>
</tr>
<tr>
<td><code>--reinstall</code></td>
<td>重新安装已经安装但可能存在问题的软件包</td>
</tr>
<tr>
<td><code>--install-suggests</code></td>
<td>同时安装 APT 给出的建议安装的软件包</td>
</tr>
</tbody></table>
<h3 id="安装软件包"><a href="#安装软件包" class="headerlink" title="安装软件包"></a>安装软件包</h3><p>关于安装，如前面演示的一样你只需要执行 <code>apt-get install &lt;packagename&gt;</code> 即可，除了这一点，你还应该掌握的是如何重新安装软件包。</p>
<p>很多时候我们需要重新安装一个软件包，比如你的系统被破坏，或者一些错误的配置导致软件无法正常工作。你可以使用如下方式重新安装：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get --reinstall install &lt;packagename&gt;</span><br></pre></td></tr></table></figure>

<p>另一个你需要掌握的是，如何在不知道软件包完整名的时候进行安装。通常我们是使用 <code>Tab</code> 键补全软件包名，后面会介绍更好的方法来搜索软件包。有时候你需要同时安装多个软件包，你还可以使用正则表达式匹配软件包名进行批量安装。</p>
<h3 id="软件升级"><a href="#软件升级" class="headerlink" title="软件升级"></a>软件升级</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 更新软件源</span><br><span class="line">sudo apt-get update</span><br><span class="line"></span><br><span class="line"># 升级没有依赖问题的软件包</span><br><span class="line">sudo apt-get upgrade</span><br><span class="line"></span><br><span class="line"># 升级并解决依赖关系</span><br><span class="line">sudo apt-get dist-upgrade</span><br></pre></td></tr></table></figure>

<h3 id="卸载软件"><a href="#卸载软件" class="headerlink" title="卸载软件"></a>卸载软件</h3><p>如果你现在觉得 <code>w3m</code> 这个软件不合自己的胃口或者是找到了更好的，你需要卸载它。那么简单，同样是一个命令加回车 <code>sudo apt-get remove w3m</code>，系统会有一个确认的操作，之后这个软件就被卸载了。</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532415931977.png" alt="此处输入图片的描述"></p>
<p>或者，你可以执行</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 不保留配置文件的移除</span><br><span class="line">sudo apt-get purge w3m</span><br><span class="line"># 或者</span><br><span class="line">sudo apt-get --purge remove w3m</span><br><span class="line"># 移除不再需要的被依赖的软件包</span><br><span class="line">sudo apt-get autoremove</span><br></pre></td></tr></table></figure>

<h3 id="软件搜索"><a href="#软件搜索" class="headerlink" title="软件搜索"></a>软件搜索</h3><p>当自己刚知道了一个软件，想下载使用，需要确认软件仓库里面有没有，就需要用到搜索功能了，命令如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-cache search softname1 softname2 softname3……</span><br></pre></td></tr></table></figure>

<p><code>apt-cache</code> 命令则是针对本地数据进行相关操作的工具，<code>search</code> 顾名思义在本地的数据库中寻找有关 <code>softname1</code>，<code>softname2</code> 相关软件的信息。现在我们试试搜索一下之前我们安装的软件 <code>w3m</code>，如图：</p>
<p><img src="https://doc.shiyanlou.com/document-uid600404labid6129timestamp1523958065018.png" alt="此处输入图片的描述"></p>
<p>结果显示了 4 个 <code>w3m</code> 相关的软件，并且有相关软件的简介。</p>
<p>关于在线安装的内容我们就介绍这么多，想了解更多关于 APT 的内容，你可以参考：</p>
<ul>
<li><a target="_blank" rel="noopener" href="http://www.debian.org/doc/manuals/apt-howto/index.zh-cn.html#contents">APT HowTo</a></li>
</ul>
<h2 id="使用-dpkg"><a href="#使用-dpkg" class="headerlink" title="使用 dpkg"></a>使用 dpkg</h2><p><strong>dpkg 介绍</strong></p>
<blockquote>
<p>dpkg 是 Debian 软件包管理器的基础，它被伊恩·默多克创建于 1993 年。dpkg 与 RPM 十分相似，同样被用于安装、卸载和供给和 .deb 软件包相关的信息。</p>
</blockquote>
<blockquote>
<p>dpkg 本身是一个底层的工具。上层的工具，像是 APT，被用于从远程获取软件包以及处理复杂的软件包关系。”dpkg”是”Debian Package”的简写。</p>
</blockquote>
<p>我们经常可以在网络上见到以<code>deb</code>形式打包的软件包，就需要使用<code>dpkg</code>命令来安装。</p>
<p><code>dpkg</code>常用参数介绍：</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td><code>-i</code></td>
<td>安装指定 deb 包</td>
</tr>
<tr>
<td><code>-R</code></td>
<td>后面加上目录名，用于安装该目录下的所有 deb 安装包</td>
</tr>
<tr>
<td><code>-r</code></td>
<td>remove，移除某个已安装的软件包</td>
</tr>
<tr>
<td><code>-I</code></td>
<td>显示 <code>deb</code> 包文件的信息</td>
</tr>
<tr>
<td><code>-s</code></td>
<td>显示已安装软件的信息</td>
</tr>
<tr>
<td><code>-S</code></td>
<td>搜索已安装的软件包</td>
</tr>
<tr>
<td><code>-L</code></td>
<td>显示已安装软件包的目录信息</td>
</tr>
</tbody></table>
<h3 id="使用-dpkg-安装-deb-软件包"><a href="#使用-dpkg-安装-deb-软件包" class="headerlink" title="使用 dpkg 安装 deb 软件包"></a>使用 dpkg 安装 deb 软件包</h3><p>我们先使用<code>apt-get</code>加上<code>-d</code>参数只下载不安装，下载 emacs 编辑器的 deb 包：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get -d install -y emacs</span><br></pre></td></tr></table></figure>

<p>下载完成后，我们可以查看&#x2F;var&#x2F;cache&#x2F;apt&#x2F;archives&#x2F;目录下的内容，如下图：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416001019.png" alt="此处输入图片的描述"></p>
<p>然后我们将第一个<code>deb</code>拷贝到 &#x2F;home&#x2F;shiyanlou 目录下，并使用<code>dpkg</code>安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cp /var/cache/apt/archives/emacs24_24.5+1-6ubuntu1.1_amd64.deb ~</span><br><span class="line"># 安装之前参看deb包的信息</span><br><span class="line">sudo dpkg -I emacs24_24.5+1-6ubuntu1.1_amd64.deb</span><br></pre></td></tr></table></figure>

<p>如你所见，这个包还额外依赖了一些软件包，这意味着，如果主机目前没有这些被依赖的软件包，直接使用 dpkg 安装可能会存在一些问题，因为<code>dpkg</code>并不能为你解决依赖关系。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"># 使用dpkg安装</span><br><span class="line">sudo dpkg -i emacs24_24.5+1-6ubuntu1.1_amd64.deb</span><br></pre></td></tr></table></figure>

<p>跟前面预料的一样，这里你可能出现了一些错误：</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416027450.png" alt="此处输入图片的描述"></p>
<p>我们将如何解决这个错误呢？这就要用到<code>apt-get</code>了，使用它的<code>-f</code>参数了，修复依赖关系的安装</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get -f install -y</span><br></pre></td></tr></table></figure>

<p>没有任何错误，这样我们就安装成功了，然后你可以运行 emacs 程序</p>
<p><img src="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416061661.png" alt="此处输入图片的描述"></p>
<h3 id="查看已安装软件包的安装目录"><a href="#查看已安装软件包的安装目录" class="headerlink" title="查看已安装软件包的安装目录"></a>查看已安装软件包的安装目录</h3><p>如果你依然在纠结到底 linux 将软件安装到了什么地方，那么很幸运你将可以通过<code>dpkg</code>找到答案</p>
<p>使用<code>dpkg -L</code>查看<code>deb</code>包目录信息</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo dpkg -L emacs24</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/document-uid735639labid356timestamp1532416074969.png" alt="此处输入图片的描述"></p>
<p><code>dpkg</code>还有一些其他的参数，这里将作为练习题由你自己来学习</p>
<h2 id="从二进制包安装"><a href="#从二进制包安装" class="headerlink" title="从二进制包安装"></a>从二进制包安装</h2><p>二进制包的安装比较简单，我们需要做的只是将从网络上下载的二进制包解压后放到合适的目录，然后将包含可执行的主程序文件的目录添加进<code>PATH</code>环境变量即可，如果你不知道该放到什么位置，请重新复习第四节关于 Linux 目录结构的内容。 </p>
<h1 id="Linux-进程概念"><a href="#Linux-进程概念" class="headerlink" title="Linux 进程概念"></a>Linux 进程概念</h1><h2 id="概念的理解"><a href="#概念的理解" class="headerlink" title="概念的理解"></a>概念的理解</h2><p>首先程序与进程是什么？程序与进程又有什么区别？</p>
<blockquote>
<p><strong>程序</strong>（procedure）：不太精确地说，程序就是执行一系列有逻辑、有顺序结构的指令，帮我们达成某个结果。就如我们去餐馆，给服务员说我要牛肉盖浇饭，她执行了做牛肉盖浇饭这么一个程序，最后我们得到了这么一盘牛肉盖浇饭。它需要去执行，不然它就像一本武功秘籍，放在那里等人翻看。</p>
</blockquote>
<blockquote>
<p><strong>进程</strong>（process）：进程是程序在一个数据集合上的一次执行过程，在早期的 UNIX、Linux 2.4 及更早的版本中，它是系统进行资源分配和调度的独立基本单位。同上一个例子，就如我们去了餐馆，给服务员说我要牛肉盖浇饭，她执行了做牛肉盖浇饭这么一个程序，而里面做饭的是一个进程，做牛肉汤汁的是一个进程，把牛肉汤汁与饭混合在一起的是一个进程，把饭端上桌的是一个进程。它就像是我们在看武功秘籍这么一个过程，然后一个篇章一个篇章地去练。</p>
</blockquote>
<p>简单来说，程序是为了完成某种任务而设计的软件，比如 vim 是程序。什么是进程呢？进程就是运行中的程序。</p>
<p>程序只是一些列指令的集合，是一个静止的实体，而进程不同，进程有以下的特性：</p>
<ul>
<li>动态性：进程的实质是一次程序执行的过程，有创建、撤销等状态的变化。而程序是一个静态的实体。</li>
<li>并发性：进程可以做到在一个时间段内，有多个程序在运行中。程序只是静态的实体，所以不存在并发性。</li>
<li>独立性：进程可以独立分配资源，独立接受调度，独立地运行。</li>
<li>异步性：进程以不可预知的速度向前推进。</li>
<li>结构性：进程拥有代码段、数据段、PCB（进程控制块，进程存在的唯一标志）。也正是因为有结构性，进程才可以做到独立地运行。</li>
</ul>
<blockquote>
<p><strong>并发：</strong>在一个时间段内，宏观来看有多个程序都在活动，有条不紊的执行（每一瞬间只有一个在执行，只是在一段时间有多个程序都执行过）</p>
</blockquote>
<blockquote>
<p><strong>并行：</strong>在每一个瞬间，都有多个程序都在同时执行，这个必须有多个 CPU 才行</p>
</blockquote>
<p>引入进程是因为传统意义上的程序已经不足以描述 OS 中各种活动之间的动态性、并发性、独立性还有相互制约性。程序就像一个公司，只是一些证书，文件的堆积（静态实体）。而当公司运作起来就有各个部门的区分，财务部，技术部，销售部等等，就像各个进程，各个部门之间可以独立运作，也可以有交互（独立性、并发性）。</p>
<p>而随着程序的发展越做越大，又会继续细分，从而引入了线程的概念，当代多数操作系统、Linux 2.6 及更新的版本中，进程本身不是基本运行单位，而是线程的容器。就像上述所说的，每个部门又会细分为各个工作小组（线程），而工作小组需要的资源需要向上级（进程）申请。</p>
<blockquote>
<p><strong>线程</strong>（thread）是操作系统能够进行运算调度的最小单位。它被包含在进程之中，是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流，一个进程中可以并发多个线程，每条线程并行执行不同的任务。因为线程中几乎不包含系统资源，所以执行更快、更有效率。</p>
</blockquote>
<p>简而言之，一个程序至少有一个进程，一个进程至少有一个线程。线程的划分尺度小于进程，使得多线程程序的并发性高。另外，进程在执行过程中拥有独立的内存单元，而多个线程共享内存，从而极大地提高了程序的运行效率。就如下图所示：</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469062947147" alt="实验楼"></p>
<h2 id="进程的属性"><a href="#进程的属性" class="headerlink" title="进程的属性"></a>进程的属性</h2><h3 id="进程的分类"><a href="#进程的分类" class="headerlink" title="进程的分类"></a>进程的分类</h3><p>大概明白进程是个什么样的存在后，我们需要进一步了解的就是进程分类。可以从两个角度来分：</p>
<ul>
<li>以进程的功能与服务的对象来分；</li>
<li>以应用程序的服务类型来分；</li>
</ul>
<p>第一个角度来看，我们可以分为用户进程与系统进程：</p>
<ul>
<li>用户进程：通过执行用户程序、应用程序或称之为内核之外的系统程序而产生的进程，此类进程可以在用户的控制下运行或关闭。</li>
<li>系统进程：通过执行系统内核程序而产生的进程，比如可以执行内存资源分配和进程切换等相对底层的工作；而且该进程的运行不受用户的干预，即使是 root 用户也不能干预系统进程的运行。</li>
</ul>
<p>第二角度来看，我们可以将进程分为交互进程、批处理进程、守护进程：</p>
<ul>
<li>交互进程：由一个 shell 终端启动的进程，在执行过程中，需要与用户进行交互操作，可以运行于前台，也可以运行在后台。</li>
<li>批处理进程：该进程是一个进程集合，负责按顺序启动其他的进程。</li>
<li>守护进程：守护进程是一直运行的一种进程，在 Linux 系统启动时启动，在系统关闭时终止。它们独立于控制终端并且周期性的执行某种任务或等待处理某些发生的事件。例如 httpd 进程，一直处于运行状态，等待用户的访问。还有经常用的 cron（在 centOS 系列为 crond）进程，这个进程为 crontab 的守护进程，可以周期性的执行用户设定的某些任务。</li>
</ul>
<h3 id="进程的衍生"><a href="#进程的衍生" class="headerlink" title="进程的衍生"></a>进程的衍生</h3><p>进程有这么多的种类，那么进程之间定是有相关性的，而这些有关联性的进程又是如何产生的，如何衍生的？</p>
<p>就比如我们启动了终端，就是启动了一个 bash 进程，我们可以在 bash 中再输入 bash 则会再启动一个 bash 的进程，此时第二个 bash 进程就是由第一个 bash 进程创建出来的，他们之间又是个什么关系？</p>
<p>我们一般称呼第一个 bash 进程是第二 bash 进程的父进程，第二 bash 进程是第一个 bash 进程的子进程，这层关系是如何得来的呢？</p>
<p>关于父进程与子进程便会提及这两个系统调用 <code>fork()</code> 与 <code>exec()</code></p>
<blockquote>
<p><strong>fork-exec</strong>是由 Dennis M. Ritchie 创造的</p>
</blockquote>
<blockquote>
<p><strong>fork()</strong> 是一个系统调用（system call），它的主要作用就是为当前的进程创建一个新的进程，这个新的进程就是它的子进程，这个子进程除了父进程的返回值和 PID 以外其他的都一模一样，如进程的执行代码段，内存信息，文件描述，寄存器状态等等</p>
</blockquote>
<blockquote>
<p><strong>exec()</strong> 也是系统调用，作用是切换子进程中的执行程序也就是替换其从父进程复制过来的代码段与数据段</p>
</blockquote>
<p>子进程就是父进程通过系统调用 <code>fork()</code> 而产生的复制品，<code>fork()</code> 就是把父进程的 PCB 等进程的数据结构信息直接复制过来，只是修改了 PID，所以一模一样，只有在执行 <code>exec()</code> 之后才会不同，而早先的 <code>fork()</code> 比较消耗资源后来进化成 <code>vfork()</code>，效率高了不少，感兴趣的同学可以查查为什么。</p>
<p>这就是子进程产生的由来。简单的实现逻辑就如下方所示：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">pid_t p;</span><br><span class="line"></span><br><span class="line">p = fork();</span><br><span class="line">if (p == (pid_t) -1)</span><br><span class="line">        /* ERROR */</span><br><span class="line">else if (p == 0)</span><br><span class="line">        /* CHILD */</span><br><span class="line">else</span><br><span class="line">        /* PARENT */</span><br></pre></td></tr></table></figure>

<p>既然子进程是通过父进程而衍生出来的，那么子进程的退出与资源的回收定然与父进程有很大的相关性。当一个子进程要正常的终止运行时，或者该进程结束时它的主函数 <code>main()</code> 会执行 <code>exit(n);</code> 或者 <code>return n</code>，这里的返回值 n 是一个信号，系统会把这个 SIGCHLD 信号传给其父进程，当然若是异常终止也往往是因为这个信号。</p>
<p>在将要结束时的子进程代码执行部分已经结束执行了，系统的资源也基本归还给系统了，但若是其进程的进程控制块（PCB）仍驻留在内存中，而它的 PCB 还在，代表这个进程还存在（因为 PCB 就是进程存在的唯一标志，里面有 PID 等消息），并没有消亡，这样的进程称之为僵尸进程（Zombie）。</p>
<p>如图中第四列标题是 S，S 表示的是进程的状态，而在下属的第三行的 Z 表示的是 Zombie 的意思。（ ps 命令将在后续详解）</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469027998669" alt="实验楼"></p>
<p>正常情况下，父进程会收到两个返回值：exit code（SIGCHLD 信号）与 <code>reason for termination</code> 。之后，父进程会使用 <code>wait(&amp;status)</code> 系统调用以获取子进程的退出状态，然后内核就可以从内存中释放已结束的子进程的 PCB；而如若父进程没有这么做的话，子进程的 PCB 就会一直驻留在内存中，一直留在系统中成为僵尸进程（Zombie）。</p>
<p>虽然僵尸进程是已经放弃了几乎所有内存空间，没有任何可执行代码，也不能被调度，在进程列表中保留一个位置，记载该进程的退出状态等信息供其父进程收集，从而释放它。但是 Linux 系统中能使用的 PID 是有限的，如果系统中存在有大量的僵尸进程，系统将会因为没有可用的 PID 从而导致不能产生新的进程。</p>
<p>另外如果父进程结束（非正常的结束），未能及时收回子进程，子进程仍在运行，这样的子进程称之为孤儿进程。在 Linux 系统中，孤儿进程一般会被 init 进程所“收养”，成为 init 的子进程。由 init 来做善后处理，所以它并不至于像僵尸进程那样无人问津，不管不顾，大量存在会有危害。</p>
<p>进程 0 是系统引导时创建的一个特殊进程，也称之为内核初始化，其最后一个动作就是调用 <code>fork()</code> 创建出一个子进程运行 <code>/sbin/init</code> 可执行文件，而该进程就是 PID&#x3D;1 的进程 1，而进程 0 就转为交换进程（也被称为空闲进程），进程 1 （init 进程）是第一个用户态的进程，再由它不断调用 fork() 来创建系统里其他的进程，所以它是所有进程的父进程或者祖先进程。同时它是一个守护程序，直到计算机关机才会停止。</p>
<p>通过以下的命令我们可以很明显的看到这样的结构</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pstree</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081468836854017" alt="实验楼"></p>
<p>或者从此图我们可以更加形象的看清子父进程的关系</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469030455439" alt="实验楼"></p>
<p>通过以上的显示结果我们可以看的很清楚，init 为所有进程的父进程或者说是祖先进程</p>
<p>我们还可以使用这样一个命令来看，其中 pid 就是该进程的一个唯一编号，ppid 就是该进程的父进程的 pid，command 表示的是该进程通过执行什么样的命令或者脚本而产生的</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps －fxo user,ppid,pid,pgid,command</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469004994601" alt="实验楼"></p>
<p>可以在图中看见我们执行的 ps 就是由 zsh 通过 fork-exec 创建的子进程而执行的</p>
<p>使用这样的一个命令我们也能清楚的看见 init 如上文所说是由进程 0 这个初始化进程来创建出来的子进程，而其他的进程基本是由 init 创建的子进程，或者是由它的子进程创建出来的子进程。所以 init 是用户进程的第一个进程也是所有用户进程的父进程或者祖先进程。（ps 命令将在后续课程详解）</p>
<p>就像一个树状图，而 init 进程就是这棵树的根，其他进程由根不断的发散，开枝散叶</p>
<h3 id="进程组与-Sessions"><a href="#进程组与-Sessions" class="headerlink" title="进程组与 Sessions"></a>进程组与 Sessions</h3><p>每一个进程都会是一个进程组的成员，而且这个进程组是唯一存在的，他们是依靠 PGID（process group ID）来区别的，而每当一个进程被创建的时候，它便会成为其父进程所在组中的一员。</p>
<p>一般情况，进程组的 PGID 等同于进程组的第一个成员的 PID，并且这样的进程称为该进程组的领导者，也就是领导进程，进程一般通过使用 <code>getpgrp()</code> 系统调用来寻找其所在组的 PGID，领导进程可以先终结，此时进程组依然存在，并持有相同的 PGID，直到进程组中最后一个进程终结。</p>
<p>与进程组类似，每当一个进程被创建的时候，它便会成为其父进程所在 Session 中的一员，每一个进程组都会在一个 Session 中，并且这个 Session 是唯一存在的，</p>
<p>Session 主要是针对一个 tty 建立，Session 中的每个进程都称为一个工作(job)。每个会话可以连接一个终端(control terminal)。当控制终端有输入输出时，都传递给该会话的前台进程组。Session 意义在于将多个 jobs 囊括在一个终端，并取其中的一个 job 作为前台，来直接接收该终端的输入输出以及终端信号。 其他 jobs 在后台运行。</p>
<blockquote>
<p><strong>前台</strong>（foreground）就是在终端中运行，能与你有交互的</p>
</blockquote>
<blockquote>
<p><strong>后台</strong>（background）就是在终端中运行，但是你并不能与其任何的交互，也不会显示其执行的过程</p>
</blockquote>
<h3 id="工作管理"><a href="#工作管理" class="headerlink" title="工作管理"></a>工作管理</h3><p>bash(Bourne-Again shell)支持工作控制（job control），而 sh（Bourne shell）并不支持。</p>
<p>并且每个终端或者说 bash 只能管理当前终端中的 job，不能管理其他终端中的 job。比如我当前存在两个 bash 分别为 bash1、bash2，bash1 只能管理其自己里面的 job 并不能管理 bash2 里面的 job</p>
<p>我们都知道当一个进程在前台运作时我们可以用 <code>ctrl + c</code> 来终止它，但是若是在后台的话就不行了。</p>
<p>我们可以通过 <code>&amp;</code> 这个符号，让我们的命令在后台中运行：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ls &amp;</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469036077882" alt="实验楼"></p>
<p>图中所显示的 <code>[1] 236</code>分别是该 job 的 job number 与该进程的 PID，而最后一行的 Done 表示该命令已经在后台执行完毕。</p>
<p>我们还可以通过 <code>ctrl + z</code> 使我们的当前工作停止并丢到后台中去</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469036715105" alt="实验楼"></p>
<p>被停止并放置在后台的工作我们可以使用这个命令来查看：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">jobs</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469037134869" alt="实验楼"></p>
<p>其中第一列显示的为被放置后台 job 的编号，而第二列的 <code>＋</code> 表示最近(刚刚、最后)被放置后台的 job，同时也表示预设的工作，也就是若是有什么针对后台 job 的操作，首先对预设的 job，<code>-</code> 表示倒数第二（也就是在预设之前的一个）被放置后台的工作，倒数第三个（再之前的）以后都不会有这样的符号修饰，第三列表示它们的状态，而最后一列表示该进程执行的命令。</p>
<p>我们可以通过这样的一个命令将后台的工作拿到前台来：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"># 后面不加参数提取预设工作，加参数提取指定工作的编号</span><br><span class="line"># ubuntu 在 zsh 中需要 %，在 bash 中不需要 %</span><br><span class="line">fg [%jobnumber]</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469037555070" alt="实验楼"></p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469037666320" alt="实验楼"></p>
<p>之前我们通过 <code>ctrl + z</code> 使得工作停止放置在后台，若是我们想让其在后台运作我们就使用这样一个命令：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">#与fg类似，加参则指定，不加参则取预设</span><br><span class="line">bg [%jobnumber]</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469037983282" alt="实验楼"></p>
<p>既然有方法将被放置在后台的工作提至前台或者让它从停止变成继续运行在后台，当然也有方法删除一个工作，或者重启等等。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"># kill的使用格式如下</span><br><span class="line">kill -signal %jobnumber</span><br><span class="line"></span><br><span class="line"># signal从1-64个信号值可以选择，可以这样查看</span><br><span class="line">kill －l</span><br></pre></td></tr></table></figure>

<p>其中常用的有这些信号值</p>
<table>
<thead>
<tr>
<th>信号值</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>-1</td>
<td>重新读取参数运行，类似与 restart</td>
</tr>
<tr>
<td>-2</td>
<td>如同 ctrl+c 的操作退出</td>
</tr>
<tr>
<td>-9</td>
<td>强制终止该任务</td>
</tr>
<tr>
<td>-15</td>
<td>正常的方式终止该任务</td>
</tr>
</tbody></table>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469038840624" alt="实验楼"></p>
<blockquote>
<p>若是在使用 kill ＋信号值然后直接加 pid，你将会对 pid 对应的进程进行操作。</p>
</blockquote>
<blockquote>
<p>若是在使用 kill+信号值然后 <code>％jobnumber</code>，这时所操作的对象是 job，这个数字就是就当前 bash 中后台的运行的 job 的 ID。</p>
</blockquote>
<h1 id="Linux-进程管理"><a href="#Linux-进程管理" class="headerlink" title="Linux 进程管理"></a>Linux 进程管理</h1><h2 id="进程的查看"><a href="#进程的查看" class="headerlink" title="进程的查看"></a>进程的查看</h2><h3 id="top-工具的使用"><a href="#top-工具的使用" class="headerlink" title="top 工具的使用"></a>top 工具的使用</h3><p><code>top</code> 工具是我们常用的一个查看工具，能实时的查看我们系统的一些关键信息的变化:</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">top</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469070319324" alt="实验楼"></p>
<p>top 是一个在前台执行的程序，所以执行后便进入到这样的一个交互界面，正是因为交互界面我们才可以实时的获取到系统与进程的信息。在交互界面中我们可以通过一些指令来操作和筛选。在此之前我们先来了解显示了哪些信息。</p>
<p>我们看到 top 显示的第一排，</p>
<table>
<thead>
<tr>
<th>内容</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>top</td>
<td>表示当前程序的名称</td>
</tr>
<tr>
<td>11:05:18</td>
<td>表示当前的系统的时间</td>
</tr>
<tr>
<td>up 8 days,17:12</td>
<td>表示该机器已经启动了多长时间</td>
</tr>
<tr>
<td>1 user</td>
<td>表示当前系统中只有一个用户</td>
</tr>
<tr>
<td>load average: 0.29,0.20,0.25</td>
<td>分别对应 1、5、15 分钟内 cpu 的平均负载</td>
</tr>
</tbody></table>
<p>load average 在 wikipedia 中的解释是 the system load is a measure of the amount of work that a computer system is doing 也就是对当前 CPU 工作量的度量，具体来说也就是指运行队列的平均长度，也就是等待 CPU 的平均进程数相关的一个计算值。</p>
<p>我们该如何看待这个 load average 数据呢？</p>
<p>假设我们的系统是单 CPU、单内核的，把它比喻成是一条单向的桥，把 CPU 任务比作汽车。</p>
<ul>
<li>load &#x3D; 0 的时候意味着这个桥上并没有车，cpu 没有任何任务；</li>
<li>load &lt; 1 的时候意味着桥上的车并不多，一切都还是很流畅的，cpu 的任务并不多，资源还很充足；</li>
<li>load &#x3D; 1 的时候就意味着桥已经被车给占满了，没有一点空隙，cpu 已经在全力工作了，所有的资源都被用完了，当然还好，这还在能力范围之内，只是有点慢而已；</li>
<li>load &gt; 1 的时候就意味着不仅仅是桥上已经被车占满了，就连桥外都被占满了，cpu 已经在全力工作，系统资源的用完了，但是还是有大量的进程在请求，在等待。若是这个值大于 2 表示进程请求超过 CPU 工作能力的 2 倍。而若是这个值大于 5 说明系统已经在超负荷运作了。</li>
</ul>
<p>这是单个 CPU 单核的情况，而实际生活中我们需要将得到的这个值除以我们的核数来看。我们可以通过以下的命令来查看 CPU 的个数与核心数：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">#查看物理 CPU 的个数</span><br><span class="line">cat /proc/cpuinfo | grep &quot;physical id&quot; | sort | uniq |wc -l</span><br><span class="line"></span><br><span class="line">#每个 cpu 的核心数</span><br><span class="line">cat /proc/cpuinfo | grep &quot;physical id&quot; | grep &quot;0&quot; | wc -l</span><br></pre></td></tr></table></figure>

<p>通过上面的指数我们可以得知 load 的临界值为 1 ，但是在实际生活中，比较有经验的运维或者系统管理员会将临界值定为 0.7。这里的指数都是除以核心数以后的值，不要混淆了</p>
<ul>
<li>若是 load &lt; 0.7 并不会去关注他；</li>
<li>若是 0.7&lt; load &lt; 1 的时候我们就需要稍微关注一下了，虽然还可以应付但是这个值已经离临界不远了；</li>
<li>若是 load &#x3D; 1 的时候我们就需要警惕了，因为这个时候已经没有更多的资源的了，已经在全力以赴了；</li>
<li>若是 load &gt; 5 的时候系统已经快不行了，这个时候你需要加班解决问题了</li>
</ul>
<p>通常我们都会先看 15 分钟的值来看这个大体的趋势，然后再看 5 分钟的值对比来看是否有下降的趋势。</p>
<p>查看 busybox 的代码可以知道，数据是每 5 秒钟就检查一次活跃的进程数，然后计算出该值，然后 load 从 <code>/proc/loadavg</code> 中读取的。而这个 load 的值是如何计算的呢，这是 load 的计算的源码</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">#define FSHIFT      11          /* nr of bits of precision */</span><br><span class="line">#define FIXED_1     (1&lt;&lt;FSHIFT) /* 1.0 as fixed-point(定点) */</span><br><span class="line">#define LOAD_FREQ   (5*HZ)      /* 5 sec intervals，每隔5秒计算一次平均负载值 */</span><br><span class="line">#define CALC_LOAD(load, exp, n)     \</span><br><span class="line">         load *= exp;               \</span><br><span class="line">         load += n*(FIXED_1 - exp); \</span><br><span class="line">         load &gt;&gt;= FSHIFT;</span><br><span class="line"></span><br><span class="line">unsigned long avenrun[3];</span><br><span class="line"></span><br><span class="line">EXPORT_SYMBOL(avenrun);</span><br><span class="line"></span><br><span class="line">/*</span><br><span class="line">* calc_load - given tick count, update the avenrun load estimates.</span><br><span class="line">* This is called while holding a write_lock on xtime_lock.</span><br><span class="line">*/</span><br><span class="line">static inline void calc_load(unsigned long ticks)</span><br><span class="line">&#123;</span><br><span class="line">        unsigned long active_tasks; /* fixed-point */</span><br><span class="line">        static int count = LOAD_FREQ;</span><br><span class="line">        count -= ticks;</span><br><span class="line">        if (count &lt; 0) &#123;</span><br><span class="line">                count += LOAD_FREQ;</span><br><span class="line">                active_tasks = count_active_tasks();</span><br><span class="line">                CALC_LOAD(avenrun[0], EXP_1, active_tasks);</span><br><span class="line">                CALC_LOAD(avenrun[1], EXP_5, active_tasks);</span><br><span class="line">                CALC_LOAD(avenrun[2], EXP_15, active_tasks);</span><br><span class="line">        &#125;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<blockquote>
<p>有兴趣的朋友可以研究一下，是如何计算的。代码中的后面这部分相当于它的计算公式。</p>
</blockquote>
<p>我们回归正题，来看 top 的第二行数据，基本上第二行是进程的一个情况统计：</p>
<table>
<thead>
<tr>
<th>内容</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>Tasks: 26 total</td>
<td>进程总数</td>
</tr>
<tr>
<td>1 running</td>
<td>1 个正在运行的进程数</td>
</tr>
<tr>
<td>25 sleeping</td>
<td>25 个睡眠的进程数</td>
</tr>
<tr>
<td>0 stopped</td>
<td>没有停止的进程数</td>
</tr>
<tr>
<td>0 zombie</td>
<td>没有僵尸进程数</td>
</tr>
</tbody></table>
<p>来看 top 的第三行数据，这一行基本上是 CPU 的一个使用情况的统计了：</p>
<table>
<thead>
<tr>
<th>内容</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td><code>Cpu(s): 1.0%us</code></td>
<td>用户空间进程占用 CPU 百分比</td>
</tr>
<tr>
<td><code>1.0% sy</code></td>
<td>内核空间运行占用 CPU 百分比</td>
</tr>
<tr>
<td><code>0.0%ni</code></td>
<td>用户进程空间内改变过优先级的进程占用 CPU 百分比</td>
</tr>
<tr>
<td><code>97.9%id</code></td>
<td>空闲 CPU 百分比</td>
</tr>
<tr>
<td><code>0.0%wa</code></td>
<td>等待输入输出的 CPU 时间百分比</td>
</tr>
<tr>
<td><code>0.1%hi</code></td>
<td>硬中断(Hardware IRQ)占用 CPU 的百分比</td>
</tr>
<tr>
<td><code>0.0%si</code></td>
<td>软中断(Software IRQ)占用 CPU 的百分比</td>
</tr>
<tr>
<td><code>0.0%st</code></td>
<td>(Steal time) 是 hypervisor 等虚拟服务中，虚拟 CPU 等待实际 CPU 的时间的百分比</td>
</tr>
</tbody></table>
<p>CPU 利用率是对一个时间段内 CPU 使用状况的统计，通过这个指标可以看出在某一个时间段内 CPU 被占用的情况，而 Load Average 是 CPU 的 Load，它所包含的信息不是 CPU 的使用率状况，而是在一段时间内 CPU 正在处理以及等待 CPU 处理的进程数情况统计信息，这两个指标并不一样。</p>
<p>来看 top 的第四行数据，这一行基本上是内存的一个使用情况的统计了：</p>
<table>
<thead>
<tr>
<th>内容</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>8176740 total</td>
<td>物理内存总量</td>
</tr>
<tr>
<td>8032104 used</td>
<td>使用的物理内存总量</td>
</tr>
<tr>
<td>144636 free</td>
<td>空闲内存总量</td>
</tr>
<tr>
<td>313088 buffers</td>
<td>用作内核缓存的内存量</td>
</tr>
</tbody></table>
<p><strong>注意：</strong></p>
<blockquote>
<p>系统中可用的物理内存最大值并不是 free 这个单一的值，而是 free + buffers + swap 中的 cached 的和。</p>
</blockquote>
<p>来看 top 的第五行数据，这一行基本上是交换区的一个使用情况的统计了：</p>
<table>
<thead>
<tr>
<th>内容</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>total</td>
<td>交换区总量</td>
</tr>
<tr>
<td>used</td>
<td>使用的交换区总量</td>
</tr>
<tr>
<td>free</td>
<td>空闲交换区总量</td>
</tr>
<tr>
<td>cached</td>
<td>缓冲的交换区总量，内存中的内容被换出到交换区，而后又被换入到内存，但使用过的交换区尚未被覆盖</td>
</tr>
</tbody></table>
<p>再下面就是进程的一个情况了</p>
<table>
<thead>
<tr>
<th>列名</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>PID</td>
<td>进程 id</td>
</tr>
<tr>
<td>USER</td>
<td>该进程的所属用户</td>
</tr>
<tr>
<td>PR</td>
<td>该进程执行的优先级 priority 值</td>
</tr>
<tr>
<td>NI</td>
<td>该进程的 nice 值</td>
</tr>
<tr>
<td>VIRT</td>
<td>该进程任务所使用的虚拟内存的总数</td>
</tr>
<tr>
<td>RES</td>
<td>该进程所使用的物理内存数，也称之为驻留内存数</td>
</tr>
<tr>
<td>SHR</td>
<td>该进程共享内存的大小</td>
</tr>
<tr>
<td>S</td>
<td>该进程进程的状态: S&#x3D;sleep R&#x3D;running Z&#x3D;zombie</td>
</tr>
<tr>
<td>%CPU</td>
<td>该进程 CPU 的利用率</td>
</tr>
<tr>
<td>%MEM</td>
<td>该进程内存的利用率</td>
</tr>
<tr>
<td>TIME+</td>
<td>该进程活跃的总时间</td>
</tr>
<tr>
<td>COMMAND</td>
<td>该进程运行的名字</td>
</tr>
</tbody></table>
<p><strong>注意:</strong></p>
<p><strong>NICE 值</strong>叫做静态优先级，是用户空间的一个优先级值，其取值范围是 -20 至 19。这个值越小，表示进程”优先级”越高，而值越大“优先级”越低。nice 值中的 -20 到 19，中 -20 优先级最高， 0 是默认的值，而 19 优先级最低。</p>
<p><strong>PR 值</strong>表示 Priority 值叫动态优先级，是进程在内核中实际的优先级值，进程优先级的取值范围是通过一个宏定义的，这个宏的名称是 <code>MAX_PRIO</code>，它的值为 140。Linux 实际上实现了 140 个优先级范围，取值范围是从 <code>0-139</code>，这个值越小，优先级越高。而这其中的 <code>0-99</code> 是实时进程的值，而 <code>100-139</code> 是给用户的。</p>
<p>其中 PR 中的 <code>100 to 139</code> 值部分有这么一个对应 <code>PR = 20 + (-20 to +19)</code>，这里的 <code>-20 to +19</code> 便是 nice 值，所以说两个虽然都是优先级，而且有千丝万缕的关系，但是他们的值，他们的作用范围并不相同。</p>
<p><strong>VIRT</strong> 任务所使用的虚拟内存的总数，其中包含所有的代码，数据，共享库和被换出 swap 空间的页面等所占据空间的总数。</p>
<p>在上文我们曾经说过 top 是一个前台程序，所以是一个可以交互的：</p>
<table>
<thead>
<tr>
<th>常用交互命令</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>q</td>
<td>退出程序</td>
</tr>
<tr>
<td>I</td>
<td>切换显示平均负载和启动时间的信息</td>
</tr>
<tr>
<td>P</td>
<td>根据 CPU 使用百分比大小进行排序</td>
</tr>
<tr>
<td>M</td>
<td>根据驻留内存大小进行排序</td>
</tr>
<tr>
<td>i</td>
<td>忽略闲置和僵死的进程，这是一个开关式命令</td>
</tr>
<tr>
<td>k</td>
<td>终止一个进程，系统提示输入 PID 及发送的信号值。一般终止进程用 15 信号，不能正常结束则使用 9 信号。安全模式下该命令被屏蔽。</td>
</tr>
</tbody></table>
<p>好好的利用 top 能够很有效的帮助我们观察到系统的瓶颈所在，或者是系统的问题所在。</p>
<h3 id="ps-工具的使用"><a href="#ps-工具的使用" class="headerlink" title="ps 工具的使用"></a>ps 工具的使用</h3><p>ps 也是我们最常用的查看进程的工具之一，我们通过这样的一个命令来了解一下，它能给我们带来哪些信息：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps aux</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469086224826" alt="实验楼"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps axjf</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469086474033" alt="实验楼"></p>
<p>我们来总体了解下会出现哪些信息给我们，这些信息又代表着什么（更多的 keywords 大家可以通过 <code>man ps</code> 了解）。</p>
<table>
<thead>
<tr>
<th>内容</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td><code>F</code></td>
<td>进程的标志（process flags），当 flags 值为 1 则表示此子程序只是 fork 但没有执行 exec，为 4 表示此程序使用超级管理员 root 权限</td>
</tr>
<tr>
<td><code>USER</code></td>
<td>进程的拥有用户</td>
</tr>
<tr>
<td><code>PID</code></td>
<td>进程的 ID</td>
</tr>
<tr>
<td><code>PPID</code></td>
<td>其父进程的 PID</td>
</tr>
<tr>
<td><code>SID</code></td>
<td>session 的 ID</td>
</tr>
<tr>
<td><code>TPGID</code></td>
<td>前台进程组的 ID</td>
</tr>
<tr>
<td><code>%CPU</code></td>
<td>进程占用的 CPU 百分比</td>
</tr>
<tr>
<td><code>%MEM</code></td>
<td>占用内存的百分比</td>
</tr>
<tr>
<td><code>NI</code></td>
<td>进程的 NICE 值</td>
</tr>
<tr>
<td><code>VSZ</code></td>
<td>进程使用虚拟内存大小</td>
</tr>
<tr>
<td><code>RSS</code></td>
<td>驻留内存中页的大小</td>
</tr>
<tr>
<td><code>TTY</code></td>
<td>终端 ID</td>
</tr>
<tr>
<td><code>S or STAT</code></td>
<td>进程状态</td>
</tr>
<tr>
<td><code>WCHAN</code></td>
<td>正在等待的进程资源</td>
</tr>
<tr>
<td><code>START</code></td>
<td>启动进程的时间</td>
</tr>
<tr>
<td><code>TIME</code></td>
<td>进程消耗 CPU 的时间</td>
</tr>
<tr>
<td><code>COMMAND</code></td>
<td>命令的名称和参数</td>
</tr>
</tbody></table>
<blockquote>
<p><strong>TPGID</strong>栏写着-1 的都是没有控制终端的进程，也就是守护进程</p>
</blockquote>
<blockquote>
<p><strong>STAT</strong>表示进程的状态，而进程的状态有很多，如下表所示</p>
</blockquote>
<table>
<thead>
<tr>
<th>状态</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td><code>R</code></td>
<td>Running.运行中</td>
</tr>
<tr>
<td><code>S</code></td>
<td>Interruptible Sleep.等待调用</td>
</tr>
<tr>
<td><code>D</code></td>
<td>Uninterruptible Sleep.不可中断睡眠</td>
</tr>
<tr>
<td><code>T</code></td>
<td>Stoped.暂停或者跟踪状态</td>
</tr>
<tr>
<td><code>X</code></td>
<td>Dead.即将被撤销</td>
</tr>
<tr>
<td><code>Z</code></td>
<td>Zombie.僵尸进程</td>
</tr>
<tr>
<td><code>W</code></td>
<td>Paging.内存交换</td>
</tr>
<tr>
<td><code>N</code></td>
<td>优先级低的进程</td>
</tr>
<tr>
<td><code>&lt;</code></td>
<td>优先级高的进程</td>
</tr>
<tr>
<td><code>s</code></td>
<td>进程的领导者</td>
</tr>
<tr>
<td><code>L</code></td>
<td>锁定状态</td>
</tr>
<tr>
<td><code>l</code></td>
<td>多线程状态</td>
</tr>
<tr>
<td><code>+</code></td>
<td>前台进程</td>
</tr>
</tbody></table>
<blockquote>
<p>其中的 D 是不能被中断睡眠的状态，处在这种状态的进程不接受外来的任何 signal，所以无法使用 kill 命令杀掉处于 D 状态的进程，无论是 <code>kill</code>，<code>kill -9</code> 还是 <code>kill -15</code>，一般处于这种状态可能是进程 I&#x2F;O 的时候出问题了。</p>
</blockquote>
<p>ps 工具有许多的参数，下面给大家解释部分常用的参数。</p>
<p>使用 <code>-l</code> 参数可以显示自己这次登录的 bash 相关的进程信息罗列出来：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -l</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469088103140" alt="实验楼"></p>
<p>相对来说我们更加常用下面这个命令，他将会罗列出所有的进程信息：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps aux</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469089342412" alt="实验楼"></p>
<p>若是查找其中的某个进程的话，我们还可以配合着 <code>grep</code> 和正则表达式一起使用：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps aux | grep zsh</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469089837027" alt="实验楼"></p>
<p>此外我们还可以查看时，将连同部分的进程呈树状显示出来：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps axjf</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469090040956" alt="实验楼"></p>
<p>当然如果你觉得使用这样的此时没有把你想要的信息放在一起，我们也可以是用这样的命令，来自定义我们所需要的参数显示：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ps -afxo user,ppid,pid,pgid,command</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469004994601" alt="实验楼"></p>
<p>这是一个简单而又实用的工具，想要更灵活的使用，想要知道更多的参数我们可以使用 man 来获取更多相关的信息。</p>
<h3 id="pstree-工具的使用"><a href="#pstree-工具的使用" class="headerlink" title="pstree 工具的使用"></a>pstree 工具的使用</h3><p>通过 <code>pstree</code> 可以很直接的看到相同的进程数量，最主要的还是我们可以看到所有进程之间的相关性。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pstree</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469090893467" alt="实验楼"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pstree -up</span><br></pre></td></tr></table></figure>

<table>
<thead>
<tr>
<th>参数选择</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>-A</td>
<td>程序树之间以 ASCII 字符连接</td>
</tr>
<tr>
<td>-p</td>
<td>同时列出每个 process 的 PID</td>
</tr>
<tr>
<td>-u</td>
<td>同时列出每个 process 的所属账户名称</td>
</tr>
</tbody></table>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469091089249" alt="实验楼"></p>
<h2 id="进程的管理"><a href="#进程的管理" class="headerlink" title="进程的管理"></a>进程的管理</h2><h3 id="kill-命令的掌握"><a href="#kill-命令的掌握" class="headerlink" title="kill 命令的掌握"></a>kill 命令的掌握</h3><p>上个实验中我们讲诉了进程之间是如何衍生，之间又有什么相关性，我们来回顾一下，当一个进程结束的时候或者要异常结束的时候，会向其父进程返回一个或者接收一个 SIGHUP 信号而做出的结束进程或者其他的操作，这个 SIGHUP 信号不仅可以由系统发送，我们可以使用 <code>kill</code> 来发送这个信号来操作进程的结束或者重启等等。</p>
<p>上节课程我们使用 <code>kill</code> 命令来管理我们的一些 job，这节课我们将尝试用 <code>kill</code> 来操作下一些不属于 job 范畴的进程，直接对 pid 下手。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"># 首先我们使用图形界面打开了 gedit、gvim，用 ps 可以查看到</span><br><span class="line">ps aux</span><br><span class="line"></span><br><span class="line"># 使用 9 这个信号强制结束 gedit 进程</span><br><span class="line">kill -9 1608</span><br><span class="line"></span><br><span class="line"># 我们再查找这个进程的时候就找不到了</span><br><span class="line">ps aux | grep gedit</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469092567061" alt="实验楼"></p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469092779938" alt="实验楼"></p>
<h3 id="进程的执行顺序"><a href="#进程的执行顺序" class="headerlink" title="进程的执行顺序"></a>进程的执行顺序</h3><p>我们在使用 ps 命令的时候可以看到大部分的进程都是处于休眠的状态，如果这些进程都被唤醒，那么该谁最先享受 CPU 的服务，后面的进程又该是一个什么样的顺序呢？进程调度的队列又该如何去排列呢？</p>
<p>当然就是靠该进程的优先级值来判定进程调度的优先级，而优先级的值就是上文所提到的 PR 与 nice 来控制与体现了</p>
<p>而 nice 的值我们是可以通过 nice 命令来修改的，而需要注意的是 nice 值可以调整的范围是 <code>-20 ~ 19</code>，其中 root 有着至高无上的权力，既可以调整自己的进程也可以调整其他用户的程序，并且是所有的值都可以用，而普通用户只可以调制属于自己的进程，并且其使用的范围只能是 <code>0 ~ 19</code>，因为系统为了避免一般用户抢占系统资源而设置的一个限制</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"># 这个实验在环境中无法做，因为权限不够，可以自己在本地尝试</span><br><span class="line"></span><br><span class="line"># 打开一个程序放在后台，或者用图形界面打开</span><br><span class="line">nice -n -5 vim &amp;</span><br><span class="line"></span><br><span class="line"># 用 ps 查看其优先级</span><br><span class="line">ps -afxo user,ppid,pid,stat,pri,ni,time,command | grep vim</span><br></pre></td></tr></table></figure>

<p>我们还可以用 renice 来修改已经存在的进程的优先级，同样因为权限的原因在实验环境中无法尝试。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">renice -5 pid</span><br></pre></td></tr></table></figure>

<h1 id="Linux-日志系统"><a href="#Linux-日志系统" class="headerlink" title="Linux 日志系统"></a>Linux 日志系统</h1><h2 id="常见的日志"><a href="#常见的日志" class="headerlink" title="常见的日志"></a>常见的日志</h2><p>日志是一个系统管理员，一个运维人员，甚至是开发人员不可或缺的东西，系统用久了偶尔也会出现一些错误，我们需要日志来给系统排错，在一些网络应用服务不能正常工作的时候，我们需要用日志来做问题定位，日志还是过往时间的记录本，我们可以通过它知道我们是否被不明用户登录过等等。</p>
<p>在 Linux 中大部分的发行版都内置使用 syslog 系统日志，那么通过前期的课程我们了解到常见的日志一般存放在 <code>/var/log</code> 中，我们来看看其中有哪些日志</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469406921904" alt="实验楼"></p>
<p>根据图中所显示的日志，我们可以根据服务对象粗略的将日志分为两类</p>
<ul>
<li>系统日志</li>
<li>应用日志</li>
</ul>
<p>系统日志主要是存放系统内置程序或系统内核之类的日志信息如 <code>alternatives.log</code> 、<code>btmp</code> 等等，应用日志主要是我们装的第三方应用所产生的日志如 <code>tomcat7</code> 、<code>apache2</code> 等等。</p>
<p>接下来我们来看看常见的系统日志有哪些，他们都记录了怎样的信息</p>
<table>
<thead>
<tr>
<th>日志名称</th>
<th>记录信息</th>
</tr>
</thead>
<tbody><tr>
<td>alternatives.log</td>
<td>系统的一些更新替代信息记录</td>
</tr>
<tr>
<td>apport.log</td>
<td>应用程序崩溃信息记录</td>
</tr>
<tr>
<td>apt&#x2F;history.log</td>
<td>使用 apt-get 安装卸载软件的信息记录</td>
</tr>
<tr>
<td>apt&#x2F;term.log</td>
<td>使用 apt-get 时的具体操作，如 package 的下载、打开等</td>
</tr>
<tr>
<td>auth.log</td>
<td>登录认证的信息记录</td>
</tr>
<tr>
<td>boot.log</td>
<td>系统启动时的程序服务的日志信息</td>
</tr>
<tr>
<td>btmp</td>
<td>错误的信息记录</td>
</tr>
<tr>
<td>Consolekit&#x2F;history</td>
<td>控制台的信息记录</td>
</tr>
<tr>
<td>dist-upgrade</td>
<td>dist-upgrade 这种更新方式的信息记录</td>
</tr>
<tr>
<td>dmesg</td>
<td>启动时，显示屏幕上内核缓冲信息，与硬件有关的信息</td>
</tr>
<tr>
<td>dpkg.log</td>
<td>dpkg 命令管理包的日志。</td>
</tr>
<tr>
<td>faillog</td>
<td>用户登录失败详细信息记录</td>
</tr>
<tr>
<td>fontconfig.log</td>
<td>与字体配置有关的信息记录</td>
</tr>
<tr>
<td>kern.log</td>
<td>内核产生的信息记录，在自己修改内核时有很大帮助</td>
</tr>
<tr>
<td>lastlog</td>
<td>用户的最近信息记录</td>
</tr>
<tr>
<td>wtmp</td>
<td>登录信息的记录。wtmp 可以找出谁正在进入系统，谁使用命令显示这个文件或信息等</td>
</tr>
<tr>
<td>syslog</td>
<td>系统信息记录</td>
</tr>
</tbody></table>
<p>而在本实验环境中没有 apport.log 是因为 apport 这个应用程序需要读取一些内核的信息来收集判断其他应用程序的信息，从而记录应用程序的崩溃信息。而在本实验环境中我们没有这个权限，所以将 apport 从内置应用值剔除，自然而然就没有它的日志信息了。</p>
<p>只闻其名，不见其人，我们并不能明白这些日志记录的内容。首先我们来看 <code>alternatives.log</code> 中的信息，在本实验环境中没有任何日志输出是因为刚刚启动的系统中并没有任何的更新迭代。我可以看看从其他地方截取过来的内容</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">update-alternatives 2016-07-02 13:36:16: run with --install /usr/bin/x-www-browser x-www-browser /usr/bin/google-chrome-stable 200</span><br><span class="line">update-alternatives 2016-07-02 13:36:16: run with --install /usr/bin/gnome-www-browser gnome-www-browser /usr/bin/google-chrome-stable 200</span><br><span class="line">update-alternatives 2016-07-02 13:36:16: run with --install /usr/bin/google-chrome google-chrome /usr/bin/google-chrome-stable 200</span><br></pre></td></tr></table></figure>

<p>我们可以从中得到的信息有程序作用，日期，命令，成功与否的返回码。</p>
<p>我们用这样的命令来看看 <code>auth.log</code> 中的信息：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo less /var/log/auth.log</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469409885670" alt="实验楼"></p>
<p>我们可以从中得到的信息有日期与 ip 地址的来源以及的用户与工具。</p>
<p>在 <code>/var/log/apt</code> 文件夹中有两个日志文件 <code>history.log</code> 与 <code>term.log</code>，两个日志文件的区别在于 <code>history.log</code> 主要记录了进行了哪个操作，相关的依赖有哪些，而 <code>term.log</code> 则是较为具体的一些操作，主要就是下载包，打开包，安装包等等的细节操作。</p>
<p>如果是刚刚开启的新系统，那么按理说这些日志应该都是空的。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo cat /var/log/apt/history.log</span><br><span class="line">sudo cat /var/log/apt/term.log</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/1379/871732/7bc699b28ff48cefee31fa859af518d9-0" alt="图片描述"></p>
<p>但是在实验环境中因为是启动的我们定制后的环境，所以两个日志中还残留了配置镜像的记录。可以先删除这两个文件然后再执行新的安装命令。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo rm /var/log/apt/history.log</span><br><span class="line">sudo rm /var/log/apt/term.log</span><br></pre></td></tr></table></figure>

<p>我们来安装 git 这个程序，因为实验环境里已经预装了 git，所以这里真正执行的操作是一个更新的操作，但这并不影响。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install git</span><br></pre></td></tr></table></figure>

<p><img src="https://doc.shiyanlou.com/courses/uid871732-20200807-1596779861997" alt="图片描述"></p>
<p>成功的执行之后我们再来查看两个日志的内容变化：</p>
<p><img src="https://doc.shiyanlou.com/courses/1379/871732/dc97b5ebc3c1054d4e5a6070fa36773b-0" alt="图片描述"></p>
<p>其他的日志格式也都类似于之前我们所查看的日志，主要便是时间，操作。而这其中有两个比较特殊的日志，其查看的方式比较与众不同，因为这两个日志并不是 ASCII 文件而是被编码成了二进制文件，所以我们并不能直接使用 less、cat、more 这样的工具来查看，这两个日志文件是 wtmp，lastlog</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469412303087" alt="实验楼"></p>
<p>我们查看的方法是使用 last 与 lastlog 工具来提取其中的信息</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469412472830" alt="实验楼"></p>
<p>关于这两个工具的更深入使用我们可以使用前面的学习过的 man 来查看</p>
<h2 id="配置的日志"><a href="#配置的日志" class="headerlink" title="配置的日志"></a>配置的日志</h2><p>这些日志是如何产生的？通过上面的例子我们可以看出大部分的日志信息似乎格式都很类似，并且都出现在这个文件夹中。</p>
<p>这样的实现可以通过两种方式：</p>
<ul>
<li>一种是由软件开发商自己来自定义日志格式然后指定输出日志位置；</li>
<li>一种方式就是 Linux 提供的日志服务程序，而我们这里系统日志是通过 syslog 来实现，提供日志管理服务。</li>
</ul>
<p>syslog 是一个系统日志记录程序，在早期的大部分 Linux 发行版都是内置 syslog，让其作为系统的默认日志收集工具，虽然随着时代的进步与发展，syslog 已经年老体衰跟不上时代的需求，所以他被 rsyslog 所代替了，较新的 Ubuntu、Fedora 等等都是默认使用 rsyslog 作为系统的日志收集工具</p>
<p>rsyslog 的全称是 rocket-fast system for log，它提供了高性能，高安全功能和模块化设计。rsyslog 能够接受各种各样的来源，将其输入，输出的结果到不同的目的地。rsyslog 可以提供超过每秒一百万条消息给目标文件。</p>
<p>这样能实时收集日志信息的程序是有其守护进程的，如 rsyslog 的守护进程便是 rsyslogd</p>
<p>因为一些原因本实验环境中默认并没有打开这个服务，我们可以手动开启这项服务，然后来查看</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install -y rsyslog</span><br><span class="line">sudo service rsyslog start</span><br><span class="line">ps aux | grep syslog</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469414492628" alt="实验楼"></p>
<p>既然它是一个服务，那么它便是可以配置，为我们提供一些我们自定义的服务</p>
<p>首先我们来看 rsyslog 的配置文件是什么样子的，而 rsyslog 的配置文件有两个，</p>
<ul>
<li>一个是 <code>/etc/rsyslog.conf</code></li>
<li>一个是 <code>/etc/rsyslog.d/50-default.conf</code>。</li>
</ul>
<p>第一个主要是配置的环境，也就是 rsyslog 加载什么模块，文件的所属者等；而第二个主要是配置的 Filter Conditions</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">vim /etc/rsyslog.conf</span><br><span class="line"></span><br><span class="line">vim /etc/rsyslog.d/50-default.conf</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469414801715" alt="实验楼"></p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469433052645" alt="实验楼"></p>
<p>也不知道他在写什么，我们还是来看看 rsyslog 的结构框架，数据流的走向吧。</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469416361678" alt="实验楼"></p>
<p>通过这个简单的流程图我们可以知道 rsyslog 主要是由 Input、Output、Parser 这样三个模块构成的，并且了解到数据的简单走向，首先通过 Input module 来收集消息，然后将得到的消息传给 Parser module，通过分析模块的层层处理，将真正需要的消息传给 Output module，然后便输出至日志文件中。</p>
<p>上文提到过 rsyslog 号称可以提供超过每秒一百万条消息给目标文件，怎么只是这样简单的结构。我们可以通过下图来做更深入的了解</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469415269198" alt="实验楼"></p>
<p>（图片来源于<a target="_blank" rel="noopener" href="http://www.rsyslog.com/doc/queues_analogy.html">http://www.rsyslog.com/doc/queues_analogy.html</a>）</p>
<p>Rsyslog 架构如图中所示，从图中我们可以很清楚的看见，rsyslog 还有一个核心的功能模块便是 Queue，也正是因为它才能做到如此高的并发。</p>
<p>第一个模块便是 Input，该模块的主要功能就是从各种各样的来源收集 messages，通过这些接口实现：</p>
<table>
<thead>
<tr>
<th>接口名</th>
<th>作用</th>
</tr>
</thead>
<tbody><tr>
<td>im3195</td>
<td>RFC3195 Input Module</td>
</tr>
<tr>
<td>imfile</td>
<td>Text File Input Module</td>
</tr>
<tr>
<td>imgssapi</td>
<td>GSSAPI Syslog Input Module</td>
</tr>
<tr>
<td>imjournal</td>
<td>Systemd Journal Input Module</td>
</tr>
<tr>
<td>imklog</td>
<td>Kernel Log Input Module</td>
</tr>
<tr>
<td>imkmsg</td>
<td>&#x2F;dev&#x2F;kmsg Log Input Module</td>
</tr>
<tr>
<td>impstats</td>
<td>Generate Periodic Statistics of Internal Counters</td>
</tr>
<tr>
<td>imptcp</td>
<td>Plain TCP Syslog</td>
</tr>
<tr>
<td>imrelp</td>
<td>RELP Input Module</td>
</tr>
<tr>
<td>imsolaris</td>
<td>Solaris Input Module</td>
</tr>
<tr>
<td>imtcp</td>
<td>TCP Syslog Input Module</td>
</tr>
<tr>
<td>imudp</td>
<td>UDP Syslog Input Module</td>
</tr>
<tr>
<td>imuxsock</td>
<td>Unix Socket Input</td>
</tr>
</tbody></table>
<p>而 Output 中也有许多可用的接口，可以通过 man 或者官方的文档查看</p>
<p>而这些模块接口的使用需要通过 $ModLoad 指令来加载，那么返回上文的图中，配置生效的头两行可以看懂了，默认加载了 imklog、imuxsock 这两个模块</p>
<p>在配置中 rsyslog 支持三种配置语法格式：</p>
<ul>
<li>sysklogd</li>
<li>legacy rsyslog</li>
<li>RainerScript</li>
</ul>
<p>sysklogd 是老的简单格式，一些新的语法特性不支持。而 legacy rsyslog 是以 dollar 符($)开头的语法，在 v6 及以上的版本还在支持，就如上文所说的 <code>$ModLoad</code> 还有一些插件和特性只在此语法下支持。而以 <code>$</code> 开头的指令是全局指令，全局指令是 rsyslogd 守护进程的配置指令，每行只能有一个指令。 RainnerScript 是最新的语法。在官网上 rsyslog 大多推荐这个语法格式来配置</p>
<p>老的语法格式（sysklogd &amp; legacy rsyslog）是以行为单位。新的语法格式（RainnerScript）可以分割多行。</p>
<p>注释有两种语法:</p>
<ul>
<li>井号 #</li>
<li>C-style <code>/* .. */</code></li>
</ul>
<p>执行顺序: 指令在 rsyslog.conf 文件中是从上到下的顺序执行的。</p>
<p>模板是 rsyslog 一个重要的属性，它可以控制日志的格式，支持类似 template() 语句的基于 string 或 plugin 的模板，通过它我们可以自定义日志格式。</p>
<p>legacy 格式使用 $template 的语法，不过这个在以后要移除，所以最好使用新格式 template():，以免未来突然不工作了也不知道为什么</p>
<p>模板定义的形式有四种，适用于不同的输出模块，一般简单的格式，可以使用 string 的形式，复杂的格式，建议使用 list 的形式，使用 list 的形式，可以使用一些额外的属性字段（property statement）</p>
<p>如果不指定输出模板，rsyslog 会默认使用 RSYSLOG_DEFAULT。若想更深入的学习可以查看<a target="_blank" rel="noopener" href="http://www.rsyslog.com/doc/v8-stable/configuration/index.html">官方文档</a></p>
<p>了解了 rsyslog 环境的配置文件之后，我们看向 <code>/etc/rsyslog.d/50-default.conf</code> 这个配置文件，这个文件中主要是配置的 Filter Conditions，也就是我们在流程图中所看见的 <code>Parser &amp; Filter Engine</code>，它的名字叫 Selectors 是过滤 syslog 的传统方法，他主要由两部分组成，<code>facility</code> 与 <code>priority</code>，其配置格式如下：</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">facility.priority log_location</span><br></pre></td></tr></table></figure>

<p>其中一个 priority 可以指定多个 facility，多个 facility 之间使用逗号 <code>,</code> 分割开</p>
<p>rsyslog 通过 Facility 的概念来定义日志消息的来源，以便对日志进行分类，Facility 的种类有：</p>
<table>
<thead>
<tr>
<th>类别</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>kern</td>
<td>内核消息</td>
</tr>
<tr>
<td>user</td>
<td>用户信息</td>
</tr>
<tr>
<td>mail</td>
<td>邮件系统消息</td>
</tr>
<tr>
<td>daemon</td>
<td>系统服务消息</td>
</tr>
<tr>
<td>auth</td>
<td>认证系统</td>
</tr>
<tr>
<td>authpriv</td>
<td>权限系统</td>
</tr>
<tr>
<td>syslog</td>
<td>日志系统自身消息</td>
</tr>
<tr>
<td>cron</td>
<td>计划安排</td>
</tr>
<tr>
<td>news</td>
<td>新闻信息</td>
</tr>
<tr>
<td>local0~7</td>
<td>由自定义程序使用</td>
</tr>
</tbody></table>
<p>而另外一部分 priority 也称之为 serverity level，除了日志的来源以外，对统一源产生日志消息还需要进行优先级的划分，而优先级的类别有以下几种：</p>
<table>
<thead>
<tr>
<th>类别</th>
<th>解释</th>
</tr>
</thead>
<tbody><tr>
<td>emergency</td>
<td>系统已经无法使用了</td>
</tr>
<tr>
<td>alert</td>
<td>必须立即处理的问题</td>
</tr>
<tr>
<td>critical</td>
<td>很严重了</td>
</tr>
<tr>
<td>error</td>
<td>错误</td>
</tr>
<tr>
<td>warning</td>
<td>警告信息</td>
</tr>
<tr>
<td>notice</td>
<td>系统正常，但是比较重要</td>
</tr>
<tr>
<td>informational</td>
<td>正常</td>
</tr>
<tr>
<td>debug</td>
<td>debug 的调试信息</td>
</tr>
<tr>
<td>panic</td>
<td>很严重但是已淘汰不常用</td>
</tr>
<tr>
<td>none</td>
<td>没有优先级，不记录任何日志消息</td>
</tr>
</tbody></table>
<p>我们来看看系统中的配置</p>
<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469433052645" alt="实验楼"></p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">auth,authpriv.*       /var/log/auth.log</span><br></pre></td></tr></table></figure>

<p>这里的意思是 auth 与 authpriv 的所有优先级的信息全都输出于 <code>/var/log/auth.log</code> 日志中</p>
<p>而其中有类似于这样的配置信息意思有细微的差别</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kern.*      -/var/log/kern.log</span><br></pre></td></tr></table></figure>

<p><code>-</code> 代表异步写入，也就是日志写入时不需要等待系统缓存的同步，也就是日志还在内存中缓存也可以继续写入无需等待完全写入硬盘后再写入。通常用于写入数据比较大时使用。</p>
<p>到此我们对 rsyslog 的配置就有了一定的了解，若想更深入学习模板，队列的高级应用，大家可去查看<a target="_blank" rel="noopener" href="http://www.rsyslog.com/doc/v8-stable/index.html">官网的文档</a>，需要注意的是 rsyslog 每个版本之间差异化比较大，学习之前先查看自己所使用的版本，再去查看相关的文档</p>
<p>与日志相关的还有一个还有常用的命令 <code>logger</code>，<code>logger</code> 是一个 shell 命令接口，可以通过该接口使用 Syslog 的系统日志模块，还可以从命令行直接向系统日志文件写入信息。</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">#首先将syslog启动起来</span><br><span class="line">sudo service rsyslog start</span><br><span class="line"></span><br><span class="line">#向 syslog 写入数据</span><br><span class="line">ping 127.0.0.1 | logger -it logger_test -p local3.notice &amp;</span><br><span class="line"></span><br><span class="line">#查看是否有数据写入</span><br><span class="line">sudo tail -f /var/log/syslog</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469474419356" alt="实验楼"></p>
<p>从图中我们可以看到我们成功的将 ping 的信息写入了 syslog 中，格式也就是使用的 rsyslog 的默认模板</p>
<p>我们可以通过 man 来查看 logger 的其他用法，</p>
<table>
<thead>
<tr>
<th>参数</th>
<th>内容</th>
</tr>
</thead>
<tbody><tr>
<td>-i</td>
<td>在每行都记录进程 ID</td>
</tr>
<tr>
<td>-t</td>
<td>添加 tag 标签</td>
</tr>
<tr>
<td>-p</td>
<td>设置日志的 facility 与 priority</td>
</tr>
</tbody></table>
<h2 id="转储的日志"><a href="#转储的日志" class="headerlink" title="转储的日志"></a>转储的日志</h2><p>在本地的机器中每天都有成百上千条日志被写入文件中，更别说是我们的服务器，每天都会有数十兆甚至更多的日志信息被写入文件中，如果是这样的话，每天看着我们的日志文件不断的膨胀，那岂不是要占用许多的空间，所以有个叫 logrotate 的东西诞生了。</p>
<p>logrotate 程序是一个日志文件管理工具。用来把旧的日志文件删除，并创建新的日志文件。我们可以根据日志文件的大小，也可以根据其天数来切割日志、管理日志，这个过程又叫做“转储”。</p>
<p>大多数 Linux 发行版使用 logrotate 或 newsyslog 对日志进行管理。logrotate 程序不但可以压缩日志文件，减少存储空间，还可以将日志发送到指定 E-mail，方便管理员及时查看日志。</p>
<p>显而易见，logrotate 是基于 CRON 来运行的，其脚本是 &#x2F;etc&#x2F;cron.daily&#x2F;logrotate；同时我们可以在 <code>/etc/logrotate</code> 中找到其配置文件</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /etc/logrotate.conf</span><br></pre></td></tr></table></figure>

<p><img src="https://dn-simplecloud.shiyanlou.com/1135081469476364695" alt="实验楼"></p>
<p>这其中的具体意思是什么呢？</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"># see &quot;man logrotate&quot; for details  //可以查看帮助文档</span><br><span class="line"># rotate log files weekly</span><br><span class="line">weekly                             //设置每周转储一次(daily、weekly、monthly当然可以使用这些参数每天、星期，月 )</span><br><span class="line"># keep 4 weeks worth of backlogs</span><br><span class="line">rotate 4                           //最多转储4次</span><br><span class="line"># create new (empty) log files after rotating old ones</span><br><span class="line">create                             //当转储后文件不存在时创建它</span><br><span class="line"># uncomment this if you want your log files compressed</span><br><span class="line">compress                          //通过gzip压缩方式转储（nocompress可以不压缩）</span><br><span class="line"># RPM packages drop log rotation information into this directory</span><br><span class="line">include /etc/logrotate.d           //其他日志文件的转储方式配置文件，包含在该目录下</span><br><span class="line"># no packages own wtmp -- we&#x27;ll rotate them here</span><br><span class="line">/var/log/wtmp &#123;                    //设置/var/log/wtmp日志文件的转储参数</span><br><span class="line">    monthly                        //每月转储</span><br><span class="line">    create 0664 root utmp          //转储后文件不存在时创建它，文件所有者为root，所属组为utmp，对应的权限为0664</span><br><span class="line">    rotate 1                       //最多转储一次</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure>

<p>当然在 &#x2F;etc&#x2F;logrotate.d&#x2F; 中有各项应用的 logrotate 配置，还有更多的配置参数，大家可以使用 man 查看，如按文件大小转储，按当前时间格式命名等等参数配置。</p>

    </div>

    
    
    

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/xlrblog/tags/Linux/" rel="tag"># Linux</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/xlrblog/2023/07/31/MyBatisPlus%E5%AD%A6%E4%B9%A0/" rel="prev" title="MyBatisPlus学习">
      <i class="fa fa-chevron-left"></i> MyBatisPlus学习
    </a></div>
      <div class="post-nav-item">
    <a href="/xlrblog/2023/09/02/SpringBoot%E5%AE%9E%E7%94%A8%E7%AF%87/" rel="next" title="SpringBoot实用篇(多环境，日志，配置，测试)">
      SpringBoot实用篇(多环境，日志，配置，测试) <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%8F%8A%E6%93%8D%E4%BD%9C"><span class="nav-number">1.</span> <span class="nav-text">基本概念及操作</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Linux%E7%BB%88%E7%AB%AF"><span class="nav-number">1.1.</span> <span class="nav-text">Linux终端</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#Shell"><span class="nav-number">1.1.1.</span> <span class="nav-text">Shell</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%91%BD%E4%BB%A4%E8%A1%8C%E6%93%8D%E4%BD%9C%E4%BD%93%E9%AA%8C"><span class="nav-number">1.1.2.</span> <span class="nav-text">命令行操作体验</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%BC%80%E5%A7%8B"><span class="nav-number">1.1.2.1.</span> <span class="nav-text">开始</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-%E9%87%8D%E8%A6%81%E5%BF%AB%E6%8D%B7%E9%94%AE"><span class="nav-number">1.1.2.2.</span> <span class="nav-text">1) 重要快捷键</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#Tab"><span class="nav-number">1.1.2.2.1.</span> <span class="nav-text">[Tab]</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Ctrl-c"><span class="nav-number">1.1.2.2.2.</span> <span class="nav-text">[Ctrl+c]</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#%E5%85%B6%E4%BB%96%E4%B8%80%E4%BA%9B%E5%B8%B8%E7%94%A8%E5%BF%AB%E6%8D%B7%E9%94%AE"><span class="nav-number">1.1.2.2.3.</span> <span class="nav-text">其他一些常用快捷键</span></a></li></ol></li><li class="nav-item nav-level-4"><a class="nav-link" href="#2-%E5%AD%A6%E4%BC%9A%E5%88%A9%E7%94%A8%E5%8E%86%E5%8F%B2%E8%BE%93%E5%85%A5%E5%91%BD%E4%BB%A4"><span class="nav-number">1.1.2.3.</span> <span class="nav-text">2) 学会利用历史输入命令</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#3-%E5%AD%A6%E4%BC%9A%E4%BD%BF%E7%94%A8%E9%80%9A%E9%85%8D%E7%AC%A6"><span class="nav-number">1.1.2.4.</span> <span class="nav-text">3) 学会使用通配符</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#4-%E5%AD%A6%E4%BC%9A%E5%9C%A8%E5%91%BD%E4%BB%A4%E8%A1%8C%E4%B8%AD%E8%8E%B7%E5%8F%96%E5%B8%AE%E5%8A%A9"><span class="nav-number">1.1.2.5.</span> <span class="nav-text">4) 学会在命令行中获取帮助</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%94%A8%E6%88%B7%E5%8F%8A%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90%E7%AE%A1%E7%90%86"><span class="nav-number">2.</span> <span class="nav-text">用户及文件权限管理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Linux%E7%94%A8%E6%88%B7%E7%AE%A1%E7%90%86"><span class="nav-number">2.1.</span> <span class="nav-text">Linux用户管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E7%94%A8%E6%88%B7"><span class="nav-number">2.1.1.</span> <span class="nav-text">查看用户</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA%E7%94%A8%E6%88%B7"><span class="nav-number">2.1.2.</span> <span class="nav-text">创建用户</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#su%EF%BC%8Csu-%E4%B8%8E-sudo"><span class="nav-number">2.1.2.1.</span> <span class="nav-text">su，su- 与 sudo</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%94%A8%E6%88%B7%E7%BB%84"><span class="nav-number">2.1.3.</span> <span class="nav-text">用户组</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%96%B9%E6%B3%95%E4%B8%80%EF%BC%9A%E4%BD%BF%E7%94%A8-groups-%E5%91%BD%E4%BB%A4"><span class="nav-number">2.1.3.1.</span> <span class="nav-text">方法一：使用 groups 命令</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%96%B9%E6%B3%95%E4%BA%8C%EF%BC%9A%E6%9F%A5%E7%9C%8B-etc-group-%E6%96%87%E4%BB%B6"><span class="nav-number">2.1.3.2.</span> <span class="nav-text">方法二：查看 &#x2F;etc&#x2F;group 文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%86%E5%85%B6%E5%AE%83%E7%94%A8%E6%88%B7%E5%8A%A0%E5%85%A5-sudo-%E7%94%A8%E6%88%B7%E7%BB%84"><span class="nav-number">2.1.3.3.</span> <span class="nav-text">将其它用户加入 sudo 用户组</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%A0%E9%99%A4%E7%94%A8%E6%88%B7%E5%92%8C%E7%94%A8%E6%88%B7%E7%BB%84"><span class="nav-number">2.1.4.</span> <span class="nav-text">删除用户和用户组</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Linux-%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90"><span class="nav-number">2.2.</span> <span class="nav-text">Linux 文件权限</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90"><span class="nav-number">2.2.1.</span> <span class="nav-text">查看文件权限</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8F%98%E6%9B%B4%E6%96%87%E4%BB%B6%E6%89%80%E6%9C%89%E8%80%85"><span class="nav-number">2.2.2.</span> <span class="nav-text">变更文件所有者</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BF%AE%E6%94%B9%E6%96%87%E4%BB%B6%E6%9D%83%E9%99%90"><span class="nav-number">2.2.3.</span> <span class="nav-text">修改文件权限</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%9B%B4%E5%A4%9A"><span class="nav-number">2.3.</span> <span class="nav-text">更多</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84%E5%8F%8A%E6%96%87%E4%BB%B6%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C"><span class="nav-number">3.</span> <span class="nav-text">Linux目录结构及文件基本操作</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#Linux%E7%9B%AE%E5%BD%95%E7%BB%93%E6%9E%84"><span class="nav-number">3.1.</span> <span class="nav-text">Linux目录结构</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#FHS-%E6%A0%87%E5%87%86"><span class="nav-number">3.1.1.</span> <span class="nav-text">FHS 标准</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%9B%AE%E5%BD%95%E8%B7%AF%E5%BE%84"><span class="nav-number">3.1.2.</span> <span class="nav-text">目录路径</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%B7%AF%E5%BE%84"><span class="nav-number">3.1.2.1.</span> <span class="nav-text">路径</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BB%9D%E5%AF%B9%E8%B7%AF%E5%BE%84"><span class="nav-number">3.1.2.2.</span> <span class="nav-text">绝对路径</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%9B%B8%E5%AF%B9%E8%B7%AF%E5%BE%84"><span class="nav-number">3.1.2.3.</span> <span class="nav-text">相对路径</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Linux%E6%96%87%E4%BB%B6%E7%9A%84%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C"><span class="nav-number">3.2.</span> <span class="nav-text">Linux文件的基本操作</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%96%B0%E5%BB%BA"><span class="nav-number">3.2.1.</span> <span class="nav-text">新建</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%96%B0%E5%BB%BA%E7%A9%BA%E7%99%BD%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.1.1.</span> <span class="nav-text">新建空白文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%96%B0%E5%BB%BA%E7%9B%AE%E5%BD%95"><span class="nav-number">3.2.1.2.</span> <span class="nav-text">新建目录</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A4%8D%E5%88%B6"><span class="nav-number">3.2.2.</span> <span class="nav-text">复制</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A4%8D%E5%88%B6%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.2.1.</span> <span class="nav-text">复制文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A4%8D%E5%88%B6%E7%9B%AE%E5%BD%95"><span class="nav-number">3.2.2.2.</span> <span class="nav-text">复制目录</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%A0%E9%99%A4"><span class="nav-number">3.2.3.</span> <span class="nav-text">删除</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%A0%E9%99%A4%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.3.1.</span> <span class="nav-text">删除文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%A0%E9%99%A4%E7%9B%AE%E5%BD%95"><span class="nav-number">3.2.3.2.</span> <span class="nav-text">删除目录</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%A7%BB%E5%8A%A8%E6%96%87%E4%BB%B6%E4%B8%8E%E6%96%87%E4%BB%B6%E9%87%8D%E5%91%BD%E5%90%8D"><span class="nav-number">3.2.4.</span> <span class="nav-text">移动文件与文件重命名</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%87%8D%E5%91%BD%E5%90%8D%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.4.1.</span> <span class="nav-text">重命名文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%B9%E9%87%8F%E9%87%8D%E5%91%BD%E5%90%8D"><span class="nav-number">3.2.4.2.</span> <span class="nav-text">批量重命名</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.5.</span> <span class="nav-text">查看文件</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-cat%EF%BC%8Ctac-%E5%92%8C-nl-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.5.1.</span> <span class="nav-text">使用 cat，tac 和 nl 命令查看文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-more-%E5%92%8C-less-%E5%91%BD%E4%BB%A4%E5%88%86%E9%A1%B5%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.5.2.</span> <span class="nav-text">使用 more 和 less 命令分页查看文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-head-%E5%92%8C-tail-%E5%91%BD%E4%BB%A4%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.5.3.</span> <span class="nav-text">使用 head 和 tail 命令查看文件</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E6%96%87%E4%BB%B6%E7%B1%BB%E5%9E%8B"><span class="nav-number">3.2.6.</span> <span class="nav-text">查看文件类型</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%BC%96%E8%BE%91%E6%96%87%E4%BB%B6"><span class="nav-number">3.2.7.</span> <span class="nav-text">编辑文件</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E4%B8%8E%E6%96%87%E4%BB%B6%E6%9F%A5%E6%89%BE"><span class="nav-number">4.</span> <span class="nav-text">环境变量与文件查找</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F"><span class="nav-number">4.1.</span> <span class="nav-text">环境变量</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F-1"><span class="nav-number">4.1.1.</span> <span class="nav-text">环境变量</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%B0%B8%E4%B9%85%E7%94%9F%E6%95%88"><span class="nav-number">4.1.1.1.</span> <span class="nav-text">永久生效</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%91%BD%E4%BB%A4%E7%9A%84%E6%9F%A5%E6%89%BE%E8%B7%AF%E5%BE%84%E4%B8%8E%E9%A1%BA%E5%BA%8F"><span class="nav-number">4.1.2.</span> <span class="nav-text">命令的查找路径与顺序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%B7%BB%E5%8A%A0%E8%87%AA%E5%AE%9A%E4%B9%89%E8%B7%AF%E5%BE%84%E5%88%B0%E2%80%9C-PATH-%E2%80%9D%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F"><span class="nav-number">4.1.3.</span> <span class="nav-text">添加自定义路径到“ PATH ”环境变量</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BF%AE%E6%94%B9%E5%92%8C%E5%88%A0%E9%99%A4%E5%B7%B2%E6%9C%89%E5%8F%98%E9%87%8F"><span class="nav-number">4.1.4.</span> <span class="nav-text">修改和删除已有变量</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%98%E9%87%8F%E4%BF%AE%E6%94%B9"><span class="nav-number">4.1.4.1.</span> <span class="nav-text">变量修改</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%98%E9%87%8F%E5%88%A0%E9%99%A4"><span class="nav-number">4.1.4.2.</span> <span class="nav-text">变量删除</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E8%AE%A9%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E7%AB%8B%E5%8D%B3%E7%94%9F%E6%95%88"><span class="nav-number">4.1.5.</span> <span class="nav-text">如何让环境变量立即生效</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%90%9C%E7%B4%A2%E6%96%87%E4%BB%B6"><span class="nav-number">4.2.</span> <span class="nav-text">搜索文件</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E6%89%93%E5%8C%85%E5%8F%8A%E8%A7%A3%E5%8E%8B%E7%BC%A9"><span class="nav-number">5.</span> <span class="nav-text">文件打包及解压缩</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5"><span class="nav-number">5.1.</span> <span class="nav-text">基本概念</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%89%93%E5%8C%85%E4%B8%8E%E8%A7%A3%E5%8E%8B%E7%BC%A9"><span class="nav-number">5.2.</span> <span class="nav-text">打包与解压缩</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#zip-%E5%8E%8B%E7%BC%A9%E6%89%93%E5%8C%85%E7%A8%8B%E5%BA%8F"><span class="nav-number">5.2.1.</span> <span class="nav-text">zip 压缩打包程序</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-unzip-%E5%91%BD%E4%BB%A4%E8%A7%A3%E5%8E%8B%E7%BC%A9-zip-%E6%96%87%E4%BB%B6"><span class="nav-number">5.2.2.</span> <span class="nav-text">使用 unzip 命令解压缩 zip 文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#tar-%E6%89%93%E5%8C%85%E5%B7%A5%E5%85%B7"><span class="nav-number">5.2.3.</span> <span class="nav-text">tar 打包工具</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%96%87%E4%BB%B6%E7%B3%BB%E7%BB%9F%E6%93%8D%E4%BD%9C%E4%B8%8E%E7%A3%81%E7%9B%98%E7%AE%A1%E7%90%86"><span class="nav-number">6.</span> <span class="nav-text">文件系统操作与磁盘管理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C"><span class="nav-number">6.1.</span> <span class="nav-text">基本操作</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E7%A3%81%E7%9B%98%E5%92%8C%E7%9B%AE%E5%BD%95%E7%9A%84%E5%AE%B9%E9%87%8F"><span class="nav-number">6.1.0.1.</span> <span class="nav-text">查看磁盘和目录的容量</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%80%E5%8D%95%E7%9A%84%E7%A3%81%E7%9B%98%E7%AE%A1%E7%90%86"><span class="nav-number">6.2.</span> <span class="nav-text">简单的磁盘管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA%E8%99%9A%E6%8B%9F%E7%A3%81%E7%9B%98"><span class="nav-number">6.2.1.</span> <span class="nav-text">创建虚拟磁盘</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#dd-%E5%91%BD%E4%BB%A4%E7%AE%80%E4%BB%8B"><span class="nav-number">6.2.1.1.</span> <span class="nav-text">dd 命令简介</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-dd-%E5%91%BD%E4%BB%A4%E5%88%9B%E5%BB%BA%E8%99%9A%E6%8B%9F%E9%95%9C%E5%83%8F%E6%96%87%E4%BB%B6"><span class="nav-number">6.2.1.2.</span> <span class="nav-text">使用 dd 命令创建虚拟镜像文件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-mkfs-%E5%91%BD%E4%BB%A4%E6%A0%BC%E5%BC%8F%E5%8C%96%E7%A3%81%E7%9B%98%EF%BC%88%E6%88%91%E4%BB%AC%E8%BF%99%E9%87%8C%E6%98%AF%E8%87%AA%E5%B7%B1%E5%88%9B%E5%BB%BA%E7%9A%84%E8%99%9A%E6%8B%9F%E7%A3%81%E7%9B%98%E9%95%9C%E5%83%8F%EF%BC%89"><span class="nav-number">6.2.1.3.</span> <span class="nav-text">使用 mkfs 命令格式化磁盘（我们这里是自己创建的虚拟磁盘镜像）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-mount-%E5%91%BD%E4%BB%A4%E6%8C%82%E8%BD%BD%E7%A3%81%E7%9B%98%E5%88%B0%E7%9B%AE%E5%BD%95%E6%A0%91"><span class="nav-number">6.2.1.4.</span> <span class="nav-text">使用 mount 命令挂载磁盘到目录树</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-umount-%E5%91%BD%E4%BB%A4%E5%8D%B8%E8%BD%BD%E5%B7%B2%E6%8C%82%E8%BD%BD%E7%A3%81%E7%9B%98"><span class="nav-number">6.2.1.5.</span> <span class="nav-text">使用 umount 命令卸载已挂载磁盘</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-fdisk-%E4%B8%BA%E7%A3%81%E7%9B%98%E5%88%86%E5%8C%BA"><span class="nav-number">6.2.1.6.</span> <span class="nav-text">使用 fdisk 为磁盘分区</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-losetup-%E5%91%BD%E4%BB%A4%E5%BB%BA%E7%AB%8B%E9%95%9C%E5%83%8F%E4%B8%8E%E5%9B%9E%E7%8E%AF%E8%AE%BE%E5%A4%87%E7%9A%84%E5%85%B3%E8%81%94"><span class="nav-number">6.2.1.7.</span> <span class="nav-text">使用 losetup 命令建立镜像与回环设备的关联</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%BD%BB%E6%9D%BE%E4%B8%80%E4%B8%8B"><span class="nav-number">6.2.1.8.</span> <span class="nav-text">轻松一下</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux-%E4%B8%8B%E7%9A%84%E5%B8%AE%E5%8A%A9%E5%91%BD%E4%BB%A4"><span class="nav-number">7.</span> <span class="nav-text">Linux 下的帮助命令</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%86%85%E5%BB%BA%E5%91%BD%E4%BB%A4%E4%B8%8E%E5%A4%96%E9%83%A8%E5%91%BD%E4%BB%A4"><span class="nav-number">7.1.</span> <span class="nav-text">内建命令与外部命令</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%AE%E5%8A%A9%E5%91%BD%E4%BB%A4%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">7.2.</span> <span class="nav-text">帮助命令的使用</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#help-%E5%91%BD%E4%BB%A4"><span class="nav-number">7.2.1.</span> <span class="nav-text">help 命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#man-%E5%91%BD%E4%BB%A4"><span class="nav-number">7.2.2.</span> <span class="nav-text">man 命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#info-%E5%91%BD%E4%BB%A4"><span class="nav-number">7.2.3.</span> <span class="nav-text">info 命令</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux-%E4%BB%BB%E5%8A%A1%E8%AE%A1%E5%88%92-crontab"><span class="nav-number">8.</span> <span class="nav-text">Linux 任务计划 crontab</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#crontab-%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">8.1.</span> <span class="nav-text">crontab 的使用</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#crontab-%E7%AE%80%E4%BB%8B"><span class="nav-number">8.1.1.</span> <span class="nav-text">crontab 简介</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#crontab-%E5%87%86%E5%A4%87"><span class="nav-number">8.1.2.</span> <span class="nav-text">crontab 准备</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#crontab-%E4%BD%BF%E7%94%A8"><span class="nav-number">8.1.3.</span> <span class="nav-text">crontab 使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#crontab-%E7%9A%84%E6%B7%B1%E5%85%A5"><span class="nav-number">8.2.</span> <span class="nav-text">crontab 的深入</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E6%8E%A7%E5%88%B6%E4%B8%8E%E7%AE%A1%E9%81%93"><span class="nav-number">9.</span> <span class="nav-text">命令执行顺序控制与管道</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%91%BD%E4%BB%A4%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F%E7%9A%84%E6%8E%A7%E5%88%B6"><span class="nav-number">9.1.</span> <span class="nav-text">命令执行顺序的控制</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E9%A1%BA%E5%BA%8F%E6%89%A7%E8%A1%8C%E5%A4%9A%E6%9D%A1%E5%91%BD%E4%BB%A4"><span class="nav-number">9.1.1.</span> <span class="nav-text">顺序执行多条命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9C%89%E9%80%89%E6%8B%A9%E7%9A%84%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4"><span class="nav-number">9.1.2.</span> <span class="nav-text">有选择的执行命令</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E7%AE%A1%E9%81%93"><span class="nav-number">9.2.</span> <span class="nav-text">管道</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%AF%95%E7%94%A8"><span class="nav-number">9.2.1.</span> <span class="nav-text">试用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#cut-%E5%91%BD%E4%BB%A4%EF%BC%8C%E6%89%93%E5%8D%B0%E6%AF%8F%E4%B8%80%E8%A1%8C%E7%9A%84%E6%9F%90%E4%B8%80%E5%AD%97%E6%AE%B5"><span class="nav-number">9.2.2.</span> <span class="nav-text">cut 命令，打印每一行的某一字段</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#grep-%E5%91%BD%E4%BB%A4%EF%BC%8C%E5%9C%A8%E6%96%87%E6%9C%AC%E4%B8%AD%E6%88%96-stdin-%E4%B8%AD%E6%9F%A5%E6%89%BE%E5%8C%B9%E9%85%8D%E5%AD%97%E7%AC%A6%E4%B8%B2"><span class="nav-number">9.2.3.</span> <span class="nav-text">grep 命令，在文本中或 stdin 中查找匹配字符串</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#wc-%E5%91%BD%E4%BB%A4%EF%BC%8C%E7%AE%80%E5%8D%95%E5%B0%8F%E5%B7%A7%E7%9A%84%E8%AE%A1%E6%95%B0%E5%B7%A5%E5%85%B7"><span class="nav-number">9.2.4.</span> <span class="nav-text">wc 命令，简单小巧的计数工具</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#sort-%E6%8E%92%E5%BA%8F%E5%91%BD%E4%BB%A4"><span class="nav-number">9.2.5.</span> <span class="nav-text">sort 排序命令</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#uniq-%E5%8E%BB%E9%87%8D%E5%91%BD%E4%BB%A4"><span class="nav-number">9.2.6.</span> <span class="nav-text">uniq 去重命令</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E7%AE%80%E5%8D%95%E7%9A%84%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86"><span class="nav-number">10.</span> <span class="nav-text">简单的文本处理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86%E5%91%BD%E4%BB%A4"><span class="nav-number">10.1.</span> <span class="nav-text">文本处理命令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#tr-%E5%91%BD%E4%BB%A4"><span class="nav-number">10.1.1.</span> <span class="nav-text">tr 命令</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F"><span class="nav-number">10.1.1.1.</span> <span class="nav-text">使用方式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E7%9A%84%E9%80%89%E9%A1%B9%E6%9C%89"><span class="nav-number">10.1.1.2.</span> <span class="nav-text">常用的选项有</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E4%B8%BE%E4%BE%8B"><span class="nav-number">10.1.1.3.</span> <span class="nav-text">操作举例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#col-%E5%91%BD%E4%BB%A4"><span class="nav-number">10.1.2.</span> <span class="nav-text">col 命令</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F-1"><span class="nav-number">10.1.2.1.</span> <span class="nav-text">使用方式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E7%9A%84%E9%80%89%E9%A1%B9%E6%9C%89-1"><span class="nav-number">10.1.2.2.</span> <span class="nav-text">常用的选项有</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E4%B8%BE%E4%BE%8B-1"><span class="nav-number">10.1.2.3.</span> <span class="nav-text">操作举例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#join-%E5%91%BD%E4%BB%A4"><span class="nav-number">10.1.3.</span> <span class="nav-text">join 命令</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F-2"><span class="nav-number">10.1.3.1.</span> <span class="nav-text">使用方式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E7%9A%84%E9%80%89%E9%A1%B9%E6%9C%89-2"><span class="nav-number">10.1.3.2.</span> <span class="nav-text">常用的选项有</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E4%B8%BE%E4%BE%8B-2"><span class="nav-number">10.1.3.3.</span> <span class="nav-text">操作举例</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#paste-%E5%91%BD%E4%BB%A4"><span class="nav-number">10.1.4.</span> <span class="nav-text">paste 命令</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E6%96%B9%E5%BC%8F-3"><span class="nav-number">10.1.4.1.</span> <span class="nav-text">使用方式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E7%94%A8%E7%9A%84%E9%80%89%E9%A1%B9%E6%9C%89-3"><span class="nav-number">10.1.4.2.</span> <span class="nav-text">常用的选项有</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%93%8D%E4%BD%9C%E4%B8%BE%E4%BE%8B-3"><span class="nav-number">10.1.4.3.</span> <span class="nav-text">操作举例</span></a></li></ol></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%B5%81%E9%87%8D%E5%AE%9A%E5%90%91"><span class="nav-number">11.</span> <span class="nav-text">数据流重定向</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%95%B0%E6%8D%AE%E6%B5%81%E9%87%8D%E5%AE%9A%E5%90%91-1"><span class="nav-number">11.1.</span> <span class="nav-text">数据流重定向</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E7%AE%80%E5%8D%95%E7%9A%84%E9%87%8D%E5%AE%9A%E5%90%91"><span class="nav-number">11.1.1.</span> <span class="nav-text">简单的重定向</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%A0%87%E5%87%86%E9%94%99%E8%AF%AF%E9%87%8D%E5%AE%9A%E5%90%91"><span class="nav-number">11.1.2.</span> <span class="nav-text">标准错误重定向</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-tee-%E5%91%BD%E4%BB%A4%E5%90%8C%E6%97%B6%E9%87%8D%E5%AE%9A%E5%90%91%E5%88%B0%E5%A4%9A%E4%B8%AA%E6%96%87%E4%BB%B6"><span class="nav-number">11.1.3.</span> <span class="nav-text">使用 tee 命令同时重定向到多个文件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%B0%B8%E4%B9%85%E9%87%8D%E5%AE%9A%E5%90%91"><span class="nav-number">11.1.4.</span> <span class="nav-text">永久重定向</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%88%9B%E5%BB%BA%E8%BE%93%E5%87%BA%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6"><span class="nav-number">11.1.5.</span> <span class="nav-text">创建输出文件描述符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%B3%E9%97%AD%E6%96%87%E4%BB%B6%E6%8F%8F%E8%BF%B0%E7%AC%A6"><span class="nav-number">11.1.6.</span> <span class="nav-text">关闭文件描述符</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%8C%E5%85%A8%E5%B1%8F%E8%94%BD%E5%91%BD%E4%BB%A4%E7%9A%84%E8%BE%93%E5%87%BA"><span class="nav-number">11.1.7.</span> <span class="nav-text">完全屏蔽命令的输出</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-xargs-%E5%88%86%E5%89%B2%E5%8F%82%E6%95%B0%E5%88%97%E8%A1%A8"><span class="nav-number">11.1.8.</span> <span class="nav-text">使用 xargs 分割参数列表</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%9F%BA%E7%A1%80"><span class="nav-number">12.</span> <span class="nav-text">正则表达式基础</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="nav-number">12.1.</span> <span class="nav-text">正则表达式</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E8%AF%AD%E6%B3%95"><span class="nav-number">12.1.1.</span> <span class="nav-text">基本语法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%80%89%E6%8B%A9"><span class="nav-number">12.1.1.1.</span> <span class="nav-text">选择</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%95%B0%E9%87%8F%E9%99%90%E5%AE%9A"><span class="nav-number">12.1.1.2.</span> <span class="nav-text">数量限定</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%8C%83%E5%9B%B4%E5%92%8C%E4%BC%98%E5%85%88%E7%BA%A7"><span class="nav-number">12.1.1.3.</span> <span class="nav-text">范围和优先级</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%AF%AD%E6%B3%95%EF%BC%88%E9%83%A8%E5%88%86%EF%BC%89"><span class="nav-number">12.1.1.4.</span> <span class="nav-text">语法（部分）</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BC%98%E5%85%88%E7%BA%A7"><span class="nav-number">12.1.1.5.</span> <span class="nav-text">优先级</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#grep-%E6%A8%A1%E5%BC%8F%E5%8C%B9%E9%85%8D%E5%91%BD%E4%BB%A4"><span class="nav-number">12.2.</span> <span class="nav-text">grep 模式匹配命令</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%9F%BA%E6%9C%AC%E6%93%8D%E4%BD%9C-1"><span class="nav-number">12.2.1.</span> <span class="nav-text">基本操作</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F"><span class="nav-number">12.2.2.</span> <span class="nav-text">使用正则表达式</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E5%9F%BA%E6%9C%AC%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%8CBRE"><span class="nav-number">12.2.2.1.</span> <span class="nav-text">使用基本正则表达式，BRE</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8%E6%89%A9%E5%B1%95%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%EF%BC%8CERE"><span class="nav-number">12.2.2.2.</span> <span class="nav-text">使用扩展正则表达式，ERE</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#sed-%E6%B5%81%E7%BC%96%E8%BE%91%E5%99%A8"><span class="nav-number">12.3.</span> <span class="nav-text">sed 流编辑器</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#sed-%E5%B8%B8%E7%94%A8%E5%8F%82%E6%95%B0%E4%BB%8B%E7%BB%8D"><span class="nav-number">12.3.1.</span> <span class="nav-text">sed 常用参数介绍</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#sed-%E7%BC%96%E8%BE%91%E5%99%A8%E7%9A%84%E6%89%A7%E8%A1%8C%E5%91%BD%E4%BB%A4%EF%BC%88%E8%BF%99%E9%87%8C%E2%80%9D%E6%89%A7%E8%A1%8C%E2%80%9C%E8%A7%A3%E9%87%8A%E4%B8%BA%E5%90%8D%E8%AF%8D%EF%BC%89"><span class="nav-number">12.3.2.</span> <span class="nav-text">sed 编辑器的执行命令（这里”执行“解释为名词）</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#sed-%E6%93%8D%E4%BD%9C%E4%B8%BE%E4%BE%8B"><span class="nav-number">12.3.3.</span> <span class="nav-text">sed 操作举例</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%89%93%E5%8D%B0%E6%8C%87%E5%AE%9A%E8%A1%8C"><span class="nav-number">12.3.3.1.</span> <span class="nav-text">打印指定行</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%A1%8C%E5%86%85%E6%9B%BF%E6%8D%A2"><span class="nav-number">12.3.3.2.</span> <span class="nav-text">行内替换</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%88%A0%E9%99%A4%E6%9F%90%E8%A1%8C"><span class="nav-number">12.3.3.3.</span> <span class="nav-text">删除某行</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#awk-%E6%96%87%E6%9C%AC%E5%A4%84%E7%90%86%E8%AF%AD%E8%A8%80"><span class="nav-number">12.4.</span> <span class="nav-text">awk 文本处理语言</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#awk-%E4%BB%8B%E7%BB%8D"><span class="nav-number">12.4.1.</span> <span class="nav-text">awk 介绍</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#awk-%E7%9A%84%E4%B8%80%E4%BA%9B%E5%9F%BA%E7%A1%80%E6%A6%82%E5%BF%B5"><span class="nav-number">12.4.2.</span> <span class="nav-text">awk 的一些基础概念</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#awk-%E5%91%BD%E4%BB%A4%E5%9F%BA%E6%9C%AC%E6%A0%BC%E5%BC%8F"><span class="nav-number">12.4.3.</span> <span class="nav-text">awk 命令基本格式</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#awk-%E6%93%8D%E4%BD%9C%E4%BD%93%E9%AA%8C"><span class="nav-number">12.4.4.</span> <span class="nav-text">awk 操作体验</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#awk-%E5%B8%B8%E7%94%A8%E7%9A%84%E5%86%85%E7%BD%AE%E5%8F%98%E9%87%8F"><span class="nav-number">12.4.5.</span> <span class="nav-text">awk 常用的内置变量</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux-%E4%B8%8B%E8%BD%AF%E4%BB%B6%E5%AE%89%E8%A3%85"><span class="nav-number">13.</span> <span class="nav-text">Linux 下软件安装</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%BC%80%E5%A7%8B-1"><span class="nav-number">13.1.</span> <span class="nav-text">开始</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%85%88%E4%BD%93%E9%AA%8C%E4%B8%80%E4%B8%8B"><span class="nav-number">13.1.1.</span> <span class="nav-text">先体验一下</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#apt-%E5%8C%85%E7%AE%A1%E7%90%86%E5%B7%A5%E5%85%B7%E4%BB%8B%E7%BB%8D"><span class="nav-number">13.1.2.</span> <span class="nav-text">apt 包管理工具介绍</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#apt-get"><span class="nav-number">13.1.3.</span> <span class="nav-text">apt-get</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%AE%89%E8%A3%85%E8%BD%AF%E4%BB%B6%E5%8C%85"><span class="nav-number">13.1.4.</span> <span class="nav-text">安装软件包</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BD%AF%E4%BB%B6%E5%8D%87%E7%BA%A7"><span class="nav-number">13.1.5.</span> <span class="nav-text">软件升级</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%8D%B8%E8%BD%BD%E8%BD%AF%E4%BB%B6"><span class="nav-number">13.1.6.</span> <span class="nav-text">卸载软件</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BD%AF%E4%BB%B6%E6%90%9C%E7%B4%A2"><span class="nav-number">13.1.7.</span> <span class="nav-text">软件搜索</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-dpkg"><span class="nav-number">13.2.</span> <span class="nav-text">使用 dpkg</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8-dpkg-%E5%AE%89%E8%A3%85-deb-%E8%BD%AF%E4%BB%B6%E5%8C%85"><span class="nav-number">13.2.1.</span> <span class="nav-text">使用 dpkg 安装 deb 软件包</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E6%9F%A5%E7%9C%8B%E5%B7%B2%E5%AE%89%E8%A3%85%E8%BD%AF%E4%BB%B6%E5%8C%85%E7%9A%84%E5%AE%89%E8%A3%85%E7%9B%AE%E5%BD%95"><span class="nav-number">13.2.2.</span> <span class="nav-text">查看已安装软件包的安装目录</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E4%BB%8E%E4%BA%8C%E8%BF%9B%E5%88%B6%E5%8C%85%E5%AE%89%E8%A3%85"><span class="nav-number">13.3.</span> <span class="nav-text">从二进制包安装</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux-%E8%BF%9B%E7%A8%8B%E6%A6%82%E5%BF%B5"><span class="nav-number">14.</span> <span class="nav-text">Linux 进程概念</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E6%A6%82%E5%BF%B5%E7%9A%84%E7%90%86%E8%A7%A3"><span class="nav-number">14.1.</span> <span class="nav-text">概念的理解</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%B1%9E%E6%80%A7"><span class="nav-number">14.2.</span> <span class="nav-text">进程的属性</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%9A%84%E5%88%86%E7%B1%BB"><span class="nav-number">14.2.1.</span> <span class="nav-text">进程的分类</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%9A%84%E8%A1%8D%E7%94%9F"><span class="nav-number">14.2.2.</span> <span class="nav-text">进程的衍生</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%BB%84%E4%B8%8E-Sessions"><span class="nav-number">14.2.3.</span> <span class="nav-text">进程组与 Sessions</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E5%B7%A5%E4%BD%9C%E7%AE%A1%E7%90%86"><span class="nav-number">14.2.4.</span> <span class="nav-text">工作管理</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux-%E8%BF%9B%E7%A8%8B%E7%AE%A1%E7%90%86"><span class="nav-number">15.</span> <span class="nav-text">Linux 进程管理</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%9A%84%E6%9F%A5%E7%9C%8B"><span class="nav-number">15.1.</span> <span class="nav-text">进程的查看</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#top-%E5%B7%A5%E5%85%B7%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">15.1.1.</span> <span class="nav-text">top 工具的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#ps-%E5%B7%A5%E5%85%B7%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">15.1.2.</span> <span class="nav-text">ps 工具的使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#pstree-%E5%B7%A5%E5%85%B7%E7%9A%84%E4%BD%BF%E7%94%A8"><span class="nav-number">15.1.3.</span> <span class="nav-text">pstree 工具的使用</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%9A%84%E7%AE%A1%E7%90%86"><span class="nav-number">15.2.</span> <span class="nav-text">进程的管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#kill-%E5%91%BD%E4%BB%A4%E7%9A%84%E6%8E%8C%E6%8F%A1"><span class="nav-number">15.2.1.</span> <span class="nav-text">kill 命令的掌握</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#%E8%BF%9B%E7%A8%8B%E7%9A%84%E6%89%A7%E8%A1%8C%E9%A1%BA%E5%BA%8F"><span class="nav-number">15.2.2.</span> <span class="nav-text">进程的执行顺序</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#Linux-%E6%97%A5%E5%BF%97%E7%B3%BB%E7%BB%9F"><span class="nav-number">16.</span> <span class="nav-text">Linux 日志系统</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#%E5%B8%B8%E8%A7%81%E7%9A%84%E6%97%A5%E5%BF%97"><span class="nav-number">16.1.</span> <span class="nav-text">常见的日志</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E9%85%8D%E7%BD%AE%E7%9A%84%E6%97%A5%E5%BF%97"><span class="nav-number">16.2.</span> <span class="nav-text">配置的日志</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#%E8%BD%AC%E5%82%A8%E7%9A%84%E6%97%A5%E5%BF%97"><span class="nav-number">16.3.</span> <span class="nav-text">转储的日志</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="君不见"
      src="/xlrblog/images/avatar.gif">
  <p class="site-author-name" itemprop="name">君不见</p>
  <div class="site-description" itemprop="description">君不见，黄河之水天上来，奔流到海不复回。</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/xlrblog/archives/">
        
          <span class="site-state-item-count">50</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
        <span class="site-state-item-count">9</span>
        <span class="site-state-item-name">分类</span>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">25</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/decxlr" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;decxlr" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2023</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">君不见</span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a> 强力驱动
  </div>

        








      </div>
    </footer>
  </div>

  
  <script src="/xlrblog/lib/anime.min.js"></script>
  <script src="/xlrblog/lib/velocity/velocity.min.js"></script>
  <script src="/xlrblog/lib/velocity/velocity.ui.min.js"></script>

<script src="/xlrblog/js/utils.js"></script>

<script src="/xlrblog/js/motion.js"></script>


<script src="/xlrblog/js/schemes/pisces.js"></script>


<script src="/xlrblog/js/next-boot.js"></script>




  




  
<script src="/xlrblog/js/local-search.js"></script>













  

  

</body>
</html>
